home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Programming / vbcc / machines / amiga68k / libsrc / math / math_040 / M68060SP / fplsp.s < prev   
Encoding:
Text File  |  1998-06-24  |  287.0 KB  |  10,981 lines

  1. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2. MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
  3. M68000 Hi-Performance Microprocessor Division
  4. M68060 Software Package
  5. Production Release P1.00 -- October 10, 1994
  6.  
  7. M68060 Software Package Copyright © 1993, 1994 Motorola Inc.  All rights reserved.
  8.  
  9. THE SOFTWARE is provided on an "AS IS" basis and without warranty.
  10. To the maximum extent permitted by applicable law,
  11. MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 
  12. INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  13. and any warranty against infringement with regard to the SOFTWARE
  14. (INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
  15.  
  16. To the maximum extent permitted by applicable law,
  17. IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
  18. (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
  19. BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
  20. ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
  21. Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
  22.  
  23. You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
  24. so long as this entire notice is retained without alteration in any modified and/or
  25. redistributed versions, and that such modified versions are clearly identified as such.
  26. No licenses are granted by implication, estoppel or otherwise under any patents
  27. or trademarks of Motorola, Inc.
  28. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  29. #
  30. # lfptop.s:
  31. #    This file is appended to the top of the 060ILSP package
  32. # and contains the entry points into the package. The user, in
  33. # effect, branches to one of the branch table entries located here.
  34. #
  35.  
  36.     bra.l    _facoss_
  37.     short    0x0000
  38.     bra.l    _facosd_
  39.     short    0x0000
  40.     bra.l    _facosx_
  41.     short    0x0000
  42.  
  43.     bra.l    _fasins_
  44.     short    0x0000
  45.     bra.l    _fasind_
  46.     short    0x0000
  47.     bra.l    _fasinx_
  48.     short    0x0000
  49.  
  50.     bra.l    _fatans_
  51.     short    0x0000
  52.     bra.l    _fatand_
  53.     short    0x0000
  54.     bra.l    _fatanx_
  55.     short    0x0000
  56.  
  57.     bra.l    _fatanhs_
  58.     short    0x0000
  59.     bra.l    _fatanhd_
  60.     short    0x0000
  61.     bra.l    _fatanhx_
  62.     short    0x0000
  63.  
  64.     bra.l    _fcoss_
  65.     short    0x0000
  66.     bra.l    _fcosd_
  67.     short    0x0000
  68.     bra.l    _fcosx_
  69.     short    0x0000
  70.  
  71.     bra.l    _fcoshs_
  72.     short    0x0000
  73.     bra.l    _fcoshd_
  74.     short    0x0000
  75.     bra.l    _fcoshx_
  76.     short    0x0000
  77.  
  78.     bra.l    _fetoxs_
  79.     short    0x0000
  80.     bra.l    _fetoxd_
  81.     short    0x0000
  82.     bra.l    _fetoxx_
  83.     short    0x0000
  84.  
  85.     bra.l    _fetoxm1s_
  86.     short    0x0000
  87.     bra.l    _fetoxm1d_
  88.     short    0x0000
  89.     bra.l    _fetoxm1x_
  90.     short    0x0000
  91.  
  92.     bra.l    _fgetexps_
  93.     short    0x0000
  94.     bra.l    _fgetexpd_
  95.     short    0x0000
  96.     bra.l    _fgetexpx_
  97.     short    0x0000
  98.  
  99.     bra.l    _fgetmans_
  100.     short    0x0000
  101.     bra.l    _fgetmand_
  102.     short    0x0000
  103.     bra.l    _fgetmanx_
  104.     short    0x0000
  105.  
  106.     bra.l    _flog10s_
  107.     short    0x0000
  108.     bra.l    _flog10d_
  109.     short    0x0000
  110.     bra.l    _flog10x_
  111.     short    0x0000
  112.  
  113.     bra.l    _flog2s_
  114.     short    0x0000
  115.     bra.l    _flog2d_
  116.     short    0x0000
  117.     bra.l    _flog2x_
  118.     short    0x0000
  119.  
  120.     bra.l    _flogns_
  121.     short    0x0000
  122.     bra.l    _flognd_
  123.     short    0x0000
  124.     bra.l    _flognx_
  125.     short    0x0000
  126.  
  127.     bra.l    _flognp1s_
  128.     short    0x0000
  129.     bra.l    _flognp1d_
  130.     short    0x0000
  131.     bra.l    _flognp1x_
  132.     short    0x0000
  133.  
  134.     bra.l    _fmods_
  135.     short    0x0000
  136.     bra.l    _fmodd_
  137.     short    0x0000
  138.     bra.l    _fmodx_
  139.     short    0x0000
  140.  
  141.     bra.l    _frems_
  142.     short    0x0000
  143.     bra.l    _fremd_
  144.     short    0x0000
  145.     bra.l    _fremx_
  146.     short    0x0000
  147.  
  148.     bra.l    _fscales_
  149.     short    0x0000
  150.     bra.l    _fscaled_
  151.     short    0x0000
  152.     bra.l    _fscalex_
  153.     short    0x0000
  154.  
  155.     bra.l    _fsins_
  156.     short    0x0000
  157.     bra.l    _fsind_
  158.     short    0x0000
  159.     bra.l    _fsinx_
  160.     short    0x0000
  161.  
  162.     bra.l    _fsincoss_
  163.     short    0x0000
  164.     bra.l    _fsincosd_
  165.     short    0x0000
  166.     bra.l    _fsincosx_
  167.     short    0x0000
  168.  
  169.     bra.l    _fsinhs_
  170.     short    0x0000
  171.     bra.l    _fsinhd_
  172.     short    0x0000
  173.     bra.l    _fsinhx_
  174.     short    0x0000
  175.  
  176.     bra.l    _ftans_
  177.     short    0x0000
  178.     bra.l    _ftand_
  179.     short    0x0000
  180.     bra.l    _ftanx_
  181.     short    0x0000
  182.  
  183.     bra.l    _ftanhs_
  184.     short    0x0000
  185.     bra.l    _ftanhd_
  186.     short    0x0000
  187.     bra.l    _ftanhx_
  188.     short    0x0000
  189.  
  190.     bra.l    _ftentoxs_
  191.     short    0x0000
  192.     bra.l    _ftentoxd_
  193.     short    0x0000
  194.     bra.l    _ftentoxx_
  195.     short    0x0000
  196.  
  197.     bra.l    _ftwotoxs_
  198.     short    0x0000
  199.     bra.l    _ftwotoxd_
  200.     short    0x0000
  201.     bra.l    _ftwotoxx_
  202.     short    0x0000
  203.  
  204.     bra.l    _fabss_
  205.     short    0x0000
  206.     bra.l    _fabsd_
  207.     short    0x0000
  208.     bra.l    _fabsx_
  209.     short    0x0000
  210.  
  211.     bra.l    _fadds_
  212.     short    0x0000
  213.     bra.l    _faddd_
  214.     short    0x0000
  215.     bra.l    _faddx_
  216.     short    0x0000
  217.  
  218.     bra.l    _fdivs_
  219.     short    0x0000
  220.     bra.l    _fdivd_
  221.     short    0x0000
  222.     bra.l    _fdivx_
  223.     short    0x0000
  224.  
  225.     bra.l    _fints_
  226.     short    0x0000
  227.     bra.l    _fintd_
  228.     short    0x0000
  229.     bra.l    _fintx_
  230.     short    0x0000
  231.  
  232.     bra.l    _fintrzs_
  233.     short    0x0000
  234.     bra.l    _fintrzd_
  235.     short    0x0000
  236.     bra.l    _fintrzx_
  237.     short    0x0000
  238.  
  239.     bra.l    _fmuls_
  240.     short    0x0000
  241.     bra.l    _fmuld_
  242.     short    0x0000
  243.     bra.l    _fmulx_
  244.     short    0x0000
  245.  
  246.     bra.l    _fnegs_
  247.     short    0x0000
  248.     bra.l    _fnegd_
  249.     short    0x0000
  250.     bra.l    _fnegx_
  251.     short    0x0000
  252.  
  253.     bra.l    _fsqrts_
  254.     short    0x0000
  255.     bra.l    _fsqrtd_
  256.     short    0x0000
  257.     bra.l    _fsqrtx_
  258.     short    0x0000
  259.  
  260.     bra.l    _fsubs_
  261.     short    0x0000
  262.     bra.l    _fsubd_
  263.     short    0x0000
  264.     bra.l    _fsubx_
  265.     short    0x0000
  266.  
  267. # leave room for future possible additions
  268.     align    0x400
  269.  
  270. #
  271. # This file contains a set of define statements for constants
  272. # in order to promote readability within the corecode itself.
  273. #
  274.  
  275. set LOCAL_SIZE,        192            # stack frame size(bytes)
  276. set LV,            -LOCAL_SIZE        # stack offset
  277.  
  278. set EXC_SR,        0x4            # stack status register
  279. set EXC_PC,        0x6            # stack pc
  280. set EXC_VOFF,        0xa            # stacked vector offset
  281. set EXC_EA,        0xc            # stacked <ea>
  282.  
  283. set EXC_FP,        0x0            # frame pointer
  284.  
  285. set EXC_AREGS,        -68            # offset of all address regs
  286. set EXC_DREGS,        -100            # offset of all data regs
  287. set EXC_FPREGS,        -36            # offset of all fp regs
  288.  
  289. set EXC_A7,        EXC_AREGS+(7*4)        # offset of saved a7
  290. set OLD_A7,        EXC_AREGS+(6*4)        # extra copy of saved a7
  291. set EXC_A6,        EXC_AREGS+(6*4)        # offset of saved a6
  292. set EXC_A5,        EXC_AREGS+(5*4)
  293. set EXC_A4,        EXC_AREGS+(4*4)
  294. set EXC_A3,        EXC_AREGS+(3*4)
  295. set EXC_A2,        EXC_AREGS+(2*4)
  296. set EXC_A1,        EXC_AREGS+(1*4)
  297. set EXC_A0,        EXC_AREGS+(0*4)
  298. set EXC_D7,        EXC_DREGS+(7*4)
  299. set EXC_D6,        EXC_DREGS+(6*4)
  300. set EXC_D5,        EXC_DREGS+(5*4)
  301. set EXC_D4,        EXC_DREGS+(4*4)
  302. set EXC_D3,        EXC_DREGS+(3*4)
  303. set EXC_D2,        EXC_DREGS+(2*4)
  304. set EXC_D1,        EXC_DREGS+(1*4)
  305. set EXC_D0,        EXC_DREGS+(0*4)
  306.  
  307. set EXC_FP0,         EXC_FPREGS+(0*12)    # offset of saved fp0
  308. set EXC_FP1,         EXC_FPREGS+(1*12)    # offset of saved fp1
  309. set EXC_FP2,         EXC_FPREGS+(2*12)    # offset of saved fp2 (not used)
  310.  
  311. set FP_SCR1,         LV+80            # fp scratch 1
  312. set FP_SCR1_EX,     FP_SCR1+0
  313. set FP_SCR1_SGN,    FP_SCR1+2
  314. set FP_SCR1_HI,     FP_SCR1+4
  315. set FP_SCR1_LO,     FP_SCR1+8
  316.  
  317. set FP_SCR0,         LV+68            # fp scratch 0
  318. set FP_SCR0_EX,     FP_SCR0+0
  319. set FP_SCR0_SGN,    FP_SCR0+2
  320. set FP_SCR0_HI,     FP_SCR0+4
  321. set FP_SCR0_LO,     FP_SCR0+8
  322.  
  323. set FP_DST,         LV+56            # fp destination operand
  324. set FP_DST_EX,         FP_DST+0
  325. set FP_DST_SGN,        FP_DST+2
  326. set FP_DST_HI,         FP_DST+4
  327. set FP_DST_LO,         FP_DST+8
  328.  
  329. set FP_SRC,         LV+44            # fp source operand
  330. set FP_SRC_EX,         FP_SRC+0
  331. set FP_SRC_SGN,        FP_SRC+2
  332. set FP_SRC_HI,         FP_SRC+4
  333. set FP_SRC_LO,         FP_SRC+8
  334.  
  335. set USER_FPIAR,        LV+40            # FP instr address register
  336.  
  337. set USER_FPSR,        LV+36            # FP status register
  338. set FPSR_CC,        USER_FPSR+0        # FPSR condition codes
  339. set FPSR_QBYTE,        USER_FPSR+1        # FPSR qoutient byte
  340. set FPSR_EXCEPT,    USER_FPSR+2        # FPSR exception status byte
  341. set FPSR_AEXCEPT,    USER_FPSR+3        # FPSR accrued exception byte
  342.  
  343. set USER_FPCR,        LV+32            # FP control register
  344. set FPCR_ENABLE,    USER_FPCR+2        # FPCR exception enable
  345. set FPCR_MODE,        USER_FPCR+3        # FPCR rounding mode control
  346.  
  347. set L_SCR3,        LV+28            # integer scratch 3
  348. set L_SCR2,        LV+24            # integer scratch 2
  349. set L_SCR1,        LV+20            # integer scratch 1
  350.  
  351. set STORE_FLG,        LV+19            # flag: operand store (ie. not fcmp/ftst)
  352.  
  353. set EXC_TEMP2,        LV+24            # temporary space
  354. set EXC_TEMP,        LV+16            # temporary space
  355.  
  356. set DTAG,        LV+15            # destination operand type
  357. set STAG,         LV+14            # source operand type
  358.  
  359. set SPCOND_FLG,        LV+10            # flag: special case (see below)
  360.  
  361. set EXC_CC,        LV+8            # saved condition codes
  362. set EXC_EXTWPTR,    LV+4            # saved current PC (active)
  363. set EXC_EXTWORD,    LV+2            # saved extension word
  364. set EXC_CMDREG,        LV+2            # saved extension word
  365. set EXC_OPWORD,        LV+0            # saved operation word
  366.  
  367. ################################
  368.  
  369. # Helpful macros
  370.  
  371. set FTEMP,        0            # offsets within an
  372. set FTEMP_EX,         0            # extended precision
  373. set FTEMP_SGN,        2            # value saved in memory.
  374. set FTEMP_HI,         4
  375. set FTEMP_LO,         8
  376. set FTEMP_GRS,        12
  377.  
  378. set LOCAL,        0            # offsets within an
  379. set LOCAL_EX,         0            # extended precision 
  380. set LOCAL_SGN,        2            # value saved in memory.
  381. set LOCAL_HI,         4
  382. set LOCAL_LO,         8
  383. set LOCAL_GRS,        12
  384.  
  385. set DST,        0            # offsets within an
  386. set DST_EX,        0            # extended precision
  387. set DST_HI,        4            # value saved in memory.
  388. set DST_LO,        8
  389.  
  390. set SRC,        0            # offsets within an
  391. set SRC_EX,        0            # extended precision
  392. set SRC_HI,        4            # value saved in memory.
  393. set SRC_LO,        8
  394.  
  395. set SGL_LO,        0x3f81            # min sgl prec exponent
  396. set SGL_HI,        0x407e            # max sgl prec exponent
  397. set DBL_LO,        0x3c01            # min dbl prec exponent
  398. set DBL_HI,        0x43fe            # max dbl prec exponent
  399. set EXT_LO,        0x0            # min ext prec exponent
  400. set EXT_HI,        0x7ffe            # max ext prec exponent
  401.  
  402. set EXT_BIAS,        0x3fff            # extended precision bias
  403. set SGL_BIAS,        0x007f            # single precision bias
  404. set DBL_BIAS,        0x03ff            # double precision bias
  405.  
  406. set NORM,        0x00            # operand type for STAG/DTAG
  407. set ZERO,        0x01            # operand type for STAG/DTAG
  408. set INF,        0x02            # operand type for STAG/DTAG
  409. set QNAN,        0x03            # operand type for STAG/DTAG
  410. set DENORM,        0x04            # operand type for STAG/DTAG
  411. set SNAN,        0x05            # operand type for STAG/DTAG
  412. set UNNORM,        0x06            # operand type for STAG/DTAG
  413.  
  414. ##################
  415. # FPSR/FPCR bits #
  416. ##################
  417. set neg_bit,        0x3            # negative result
  418. set z_bit,        0x2            # zero result
  419. set inf_bit,        0x1            # infinite result
  420. set nan_bit,        0x0            # NAN result
  421.  
  422. set q_sn_bit,        0x7            # sign bit of quotient byte
  423.  
  424. set bsun_bit,        7            # branch on unordered
  425. set snan_bit,        6            # signalling NAN
  426. set operr_bit,        5            # operand error
  427. set ovfl_bit,        4            # overflow
  428. set unfl_bit,        3            # underflow
  429. set dz_bit,        2            # divide by zero
  430. set inex2_bit,        1            # inexact result 2
  431. set inex1_bit,        0            # inexact result 1
  432.  
  433. set aiop_bit,        7            # accrued inexact operation bit
  434. set aovfl_bit,        6            # accrued overflow bit
  435. set aunfl_bit,        5            # accrued underflow bit
  436. set adz_bit,        4            # accrued dz bit
  437. set ainex_bit,        3            # accrued inexact bit
  438.  
  439. #############################
  440. # FPSR individual bit masks #
  441. #############################
  442. set neg_mask,        0x08000000        # negative bit mask (lw)
  443. set inf_mask,        0x02000000        # infinity bit mask (lw)
  444. set z_mask,        0x04000000        # zero bit mask (lw)
  445. set nan_mask,        0x01000000        # nan bit mask (lw)
  446.  
  447. set neg_bmask,        0x08            # negative bit mask (byte)
  448. set inf_bmask,        0x02            # infinity bit mask (byte)
  449. set z_bmask,        0x04            # zero bit mask (byte)
  450. set nan_bmask,        0x01            # nan bit mask (byte)
  451.  
  452. set bsun_mask,        0x00008000        # bsun exception mask
  453. set snan_mask,        0x00004000        # snan exception mask
  454. set operr_mask,        0x00002000        # operr exception mask
  455. set ovfl_mask,        0x00001000        # overflow exception mask
  456. set unfl_mask,        0x00000800        # underflow exception mask
  457. set dz_mask,        0x00000400        # dz exception mask
  458. set inex2_mask,        0x00000200        # inex2 exception mask
  459. set inex1_mask,        0x00000100        # inex1 exception mask
  460.  
  461. set aiop_mask,        0x00000080        # accrued illegal operation
  462. set aovfl_mask,        0x00000040        # accrued overflow
  463. set aunfl_mask,        0x00000020        # accrued underflow
  464. set adz_mask,        0x00000010        # accrued divide by zero
  465. set ainex_mask,        0x00000008        # accrued inexact
  466.  
  467. ######################################
  468. # FPSR combinations used in the FPSP #
  469. ######################################
  470. set dzinf_mask,        inf_mask+dz_mask+adz_mask
  471. set opnan_mask,        nan_mask+operr_mask+aiop_mask
  472. set nzi_mask,        0x01ffffff         #clears N, Z, and I
  473. set unfinx_mask,    unfl_mask+inex2_mask+aunfl_mask+ainex_mask
  474. set unf2inx_mask,    unfl_mask+inex2_mask+ainex_mask
  475. set ovfinx_mask,    ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
  476. set inx1a_mask,        inex1_mask+ainex_mask
  477. set inx2a_mask,        inex2_mask+ainex_mask
  478. set snaniop_mask,     nan_mask+snan_mask+aiop_mask
  479. set snaniop2_mask,    snan_mask+aiop_mask
  480. set naniop_mask,    nan_mask+aiop_mask
  481. set neginf_mask,    neg_mask+inf_mask
  482. set infaiop_mask,     inf_mask+aiop_mask
  483. set negz_mask,        neg_mask+z_mask
  484. set opaop_mask,        operr_mask+aiop_mask
  485. set unfl_inx_mask,    unfl_mask+aunfl_mask+ainex_mask
  486. set ovfl_inx_mask,    ovfl_mask+aovfl_mask+ainex_mask
  487.  
  488. #########
  489. # misc. #
  490. #########
  491. set rnd_stky_bit,    29            # stky bit pos in longword
  492.  
  493. set sign_bit,        0x7            # sign bit
  494. set signan_bit,        0x6            # signalling nan bit
  495.  
  496. set sgl_thresh,        0x3f81            # minimum sgl exponent
  497. set dbl_thresh,        0x3c01            # minimum dbl exponent
  498.  
  499. set x_mode,        0x0            # extended precision
  500. set s_mode,        0x4            # single precision
  501. set d_mode,        0x8            # double precision
  502.  
  503. set rn_mode,        0x0            # round-to-nearest
  504. set rz_mode,        0x1            # round-to-zero
  505. set rm_mode,        0x2            # round-tp-minus-infinity
  506. set rp_mode,        0x3            # round-to-plus-infinity
  507.  
  508. set mantissalen,    64            # length of mantissa in bits
  509.  
  510. set BYTE,        1            # len(byte) == 1 byte
  511. set WORD,         2            # len(word) == 2 bytes
  512. set LONG,         4            # len(longword) == 2 bytes
  513.  
  514. set BSUN_VEC,        0xc0            # bsun    vector offset
  515. set INEX_VEC,        0xc4            # inexact vector offset
  516. set DZ_VEC,        0xc8            # dz      vector offset
  517. set UNFL_VEC,        0xcc            # unfl    vector offset
  518. set OPERR_VEC,        0xd0            # operr   vector offset
  519. set OVFL_VEC,        0xd4            # ovfl    vector offset
  520. set SNAN_VEC,        0xd8            # snan    vector offset
  521.  
  522. ###########################
  523. # SPecial CONDition FLaGs #
  524. ###########################
  525. set ftrapcc_flg,    0x01            # flag bit: ftrapcc exception
  526. set fbsun_flg,        0x02            # flag bit: bsun exception
  527. set mia7_flg,        0x04            # flag bit: (a7)+ <ea>
  528. set mda7_flg,        0x08            # flag bit: -(a7) <ea>
  529. set fmovm_flg,        0x40            # flag bit: fmovm instruction
  530. set immed_flg,        0x80            # flag bit: &<data> <ea>
  531.  
  532. set ftrapcc_bit,    0x0
  533. set fbsun_bit,        0x1
  534. set mia7_bit,        0x2
  535. set mda7_bit,        0x3
  536. set immed_bit,        0x7
  537.  
  538. ##################################
  539. # TRANSCENDENTAL "LAST-OP" FLAGS #
  540. ##################################
  541. set FMUL_OP,        0x0            # fmul instr performed last
  542. set FDIV_OP,        0x1            # fdiv performed last
  543. set FADD_OP,        0x2            # fadd performed last
  544. set FMOV_OP,        0x3            # fmov performed last
  545.  
  546. #############
  547. # CONSTANTS #
  548. #############
  549. T1:    long        0x40C62D38,0xD3D64634    # 16381 LOG2 LEAD
  550. T2:    long        0x3D6F90AE,0xB1E75CC7    # 16381 LOG2 TRAIL
  551.  
  552. PI:    long        0x40000000,0xC90FDAA2,0x2168C235,0x00000000
  553. PIBY2:    long        0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
  554.  
  555. TWOBYPI:
  556.     long        0x3FE45F30,0x6DC9C883
  557.  
  558. #########################################################################
  559. # MONADIC TEMPLATE                            #
  560. #########################################################################
  561.     global        _fsins_
  562. _fsins_:
  563.     link        %a6,&-LOCAL_SIZE
  564.  
  565.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  566.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  567.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  568.  
  569.     fmov.l        &0x0,%fpcr        # zero FPCR
  570.  
  571. #
  572. #    copy, convert, and tag input argument
  573. #
  574.     fmov.s        0x8(%a6),%fp0        # load sgl input
  575.     fmov.x        %fp0,FP_SRC(%a6)
  576.     lea        FP_SRC(%a6),%a0
  577.     bsr.l        tag            # fetch operand type
  578.     mov.b        %d0,STAG(%a6)
  579.     mov.b        %d0,%d1
  580.  
  581.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  582.  
  583.     clr.l        %d0
  584.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  585.  
  586.     tst.b        %d1
  587.     bne.b        _L0_2s
  588.     bsr.l        ssin            # operand is a NORM
  589.     bra.b        _L0_6s
  590. _L0_2s:
  591.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  592.     bne.b        _L0_3s            # no
  593.     bsr.l        src_zero            # yes
  594.     bra.b        _L0_6s
  595. _L0_3s:
  596.     cmpi.b        %d1,&INF        # is operand an INF?
  597.     bne.b        _L0_4s            # no
  598.     bsr.l        t_operr            # yes
  599.     bra.b        _L0_6s
  600. _L0_4s:
  601.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  602.     bne.b        _L0_5s            # no
  603.     bsr.l        src_qnan            # yes
  604.     bra.b        _L0_6s
  605. _L0_5s:
  606.     bsr.l        ssind            # operand is a DENORM
  607. _L0_6s:
  608.  
  609. #
  610. #    Result is now in FP0
  611. #
  612.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  613.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  614.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  615.     unlk        %a6
  616.     rts
  617.  
  618.     global        _fsind_
  619. _fsind_:
  620.     link        %a6,&-LOCAL_SIZE
  621.  
  622.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  623.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  624.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  625.  
  626.     fmov.l        &0x0,%fpcr        # zero FPCR
  627.  
  628. #
  629. #    copy, convert, and tag input argument
  630. #
  631.     fmov.d        0x8(%a6),%fp0        # load dbl input
  632.     fmov.x        %fp0,FP_SRC(%a6)
  633.     lea        FP_SRC(%a6),%a0
  634.     bsr.l        tag            # fetch operand type
  635.     mov.b        %d0,STAG(%a6)
  636.     mov.b        %d0,%d1
  637.  
  638.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  639.  
  640.     clr.l        %d0
  641.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  642.  
  643.     mov.b        %d1,STAG(%a6)
  644.     tst.b        %d1
  645.     bne.b        _L0_2d
  646.     bsr.l        ssin            # operand is a NORM
  647.     bra.b        _L0_6d
  648. _L0_2d:
  649.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  650.     bne.b        _L0_3d            # no
  651.     bsr.l        src_zero            # yes
  652.     bra.b        _L0_6d
  653. _L0_3d:
  654.     cmpi.b        %d1,&INF        # is operand an INF?
  655.     bne.b        _L0_4d            # no
  656.     bsr.l        t_operr            # yes
  657.     bra.b        _L0_6d
  658. _L0_4d:
  659.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  660.     bne.b        _L0_5d            # no
  661.     bsr.l        src_qnan            # yes
  662.     bra.b        _L0_6d
  663. _L0_5d:
  664.     bsr.l        ssind            # operand is a DENORM
  665. _L0_6d:
  666.  
  667. #
  668. #    Result is now in FP0
  669. #
  670.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  671.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  672.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  673.     unlk        %a6
  674.     rts
  675.  
  676.     global        _fsinx_
  677. _fsinx_:
  678.     link        %a6,&-LOCAL_SIZE
  679.  
  680.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  681.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  682.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  683.  
  684.     fmov.l        &0x0,%fpcr        # zero FPCR
  685.  
  686. #
  687. #    copy, convert, and tag input argument
  688. #
  689.     lea        FP_SRC(%a6),%a0
  690.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  691.     mov.l        0x8+0x4(%a6),0x4(%a0)
  692.     mov.l        0x8+0x8(%a6),0x8(%a0)
  693.     bsr.l        tag            # fetch operand type
  694.     mov.b        %d0,STAG(%a6)
  695.     mov.b        %d0,%d1
  696.  
  697.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  698.  
  699.     clr.l        %d0
  700.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  701.  
  702.     tst.b        %d1
  703.     bne.b        _L0_2x
  704.     bsr.l        ssin            # operand is a NORM
  705.     bra.b        _L0_6x
  706. _L0_2x:
  707.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  708.     bne.b        _L0_3x            # no
  709.     bsr.l        src_zero            # yes
  710.     bra.b        _L0_6x
  711. _L0_3x:
  712.     cmpi.b        %d1,&INF        # is operand an INF?
  713.     bne.b        _L0_4x            # no
  714.     bsr.l        t_operr            # yes
  715.     bra.b        _L0_6x
  716. _L0_4x:
  717.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  718.     bne.b        _L0_5x            # no
  719.     bsr.l        src_qnan            # yes
  720.     bra.b        _L0_6x
  721. _L0_5x:
  722.     bsr.l        ssind            # operand is a DENORM
  723. _L0_6x:
  724.  
  725. #
  726. #    Result is now in FP0
  727. #
  728.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  729.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  730.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  731.     unlk        %a6
  732.     rts
  733.  
  734.  
  735. #########################################################################
  736. # MONADIC TEMPLATE                            #
  737. #########################################################################
  738.     global        _fcoss_
  739. _fcoss_:
  740.     link        %a6,&-LOCAL_SIZE
  741.  
  742.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  743.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  744.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  745.  
  746.     fmov.l        &0x0,%fpcr        # zero FPCR
  747.  
  748. #
  749. #    copy, convert, and tag input argument
  750. #
  751.     fmov.s        0x8(%a6),%fp0        # load sgl input
  752.     fmov.x        %fp0,FP_SRC(%a6)
  753.     lea        FP_SRC(%a6),%a0
  754.     bsr.l        tag            # fetch operand type
  755.     mov.b        %d0,STAG(%a6)
  756.     mov.b        %d0,%d1
  757.  
  758.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  759.  
  760.     clr.l        %d0
  761.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  762.  
  763.     tst.b        %d1
  764.     bne.b        _L1_2s
  765.     bsr.l        scos            # operand is a NORM
  766.     bra.b        _L1_6s
  767. _L1_2s:
  768.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  769.     bne.b        _L1_3s            # no
  770.     bsr.l        ld_pone            # yes
  771.     bra.b        _L1_6s
  772. _L1_3s:
  773.     cmpi.b        %d1,&INF        # is operand an INF?
  774.     bne.b        _L1_4s            # no
  775.     bsr.l        t_operr            # yes
  776.     bra.b        _L1_6s
  777. _L1_4s:
  778.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  779.     bne.b        _L1_5s            # no
  780.     bsr.l        src_qnan            # yes
  781.     bra.b        _L1_6s
  782. _L1_5s:
  783.     bsr.l        scosd            # operand is a DENORM
  784. _L1_6s:
  785.  
  786. #
  787. #    Result is now in FP0
  788. #
  789.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  790.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  791.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  792.     unlk        %a6
  793.     rts
  794.  
  795.     global        _fcosd_
  796. _fcosd_:
  797.     link        %a6,&-LOCAL_SIZE
  798.  
  799.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  800.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  801.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  802.  
  803.     fmov.l        &0x0,%fpcr        # zero FPCR
  804.  
  805. #
  806. #    copy, convert, and tag input argument
  807. #
  808.     fmov.d        0x8(%a6),%fp0        # load dbl input
  809.     fmov.x        %fp0,FP_SRC(%a6)
  810.     lea        FP_SRC(%a6),%a0
  811.     bsr.l        tag            # fetch operand type
  812.     mov.b        %d0,STAG(%a6)
  813.     mov.b        %d0,%d1
  814.  
  815.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  816.  
  817.     clr.l        %d0
  818.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  819.  
  820.     mov.b        %d1,STAG(%a6)
  821.     tst.b        %d1
  822.     bne.b        _L1_2d
  823.     bsr.l        scos            # operand is a NORM
  824.     bra.b        _L1_6d
  825. _L1_2d:
  826.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  827.     bne.b        _L1_3d            # no
  828.     bsr.l        ld_pone            # yes
  829.     bra.b        _L1_6d
  830. _L1_3d:
  831.     cmpi.b        %d1,&INF        # is operand an INF?
  832.     bne.b        _L1_4d            # no
  833.     bsr.l        t_operr            # yes
  834.     bra.b        _L1_6d
  835. _L1_4d:
  836.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  837.     bne.b        _L1_5d            # no
  838.     bsr.l        src_qnan            # yes
  839.     bra.b        _L1_6d
  840. _L1_5d:
  841.     bsr.l        scosd            # operand is a DENORM
  842. _L1_6d:
  843.  
  844. #
  845. #    Result is now in FP0
  846. #
  847.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  848.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  849.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  850.     unlk        %a6
  851.     rts
  852.  
  853.     global        _fcosx_
  854. _fcosx_:
  855.     link        %a6,&-LOCAL_SIZE
  856.  
  857.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  858.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  859.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  860.  
  861.     fmov.l        &0x0,%fpcr        # zero FPCR
  862.  
  863. #
  864. #    copy, convert, and tag input argument
  865. #
  866.     lea        FP_SRC(%a6),%a0
  867.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  868.     mov.l        0x8+0x4(%a6),0x4(%a0)
  869.     mov.l        0x8+0x8(%a6),0x8(%a0)
  870.     bsr.l        tag            # fetch operand type
  871.     mov.b        %d0,STAG(%a6)
  872.     mov.b        %d0,%d1
  873.  
  874.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  875.  
  876.     clr.l        %d0
  877.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  878.  
  879.     tst.b        %d1
  880.     bne.b        _L1_2x
  881.     bsr.l        scos            # operand is a NORM
  882.     bra.b        _L1_6x
  883. _L1_2x:
  884.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  885.     bne.b        _L1_3x            # no
  886.     bsr.l        ld_pone            # yes
  887.     bra.b        _L1_6x
  888. _L1_3x:
  889.     cmpi.b        %d1,&INF        # is operand an INF?
  890.     bne.b        _L1_4x            # no
  891.     bsr.l        t_operr            # yes
  892.     bra.b        _L1_6x
  893. _L1_4x:
  894.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  895.     bne.b        _L1_5x            # no
  896.     bsr.l        src_qnan            # yes
  897.     bra.b        _L1_6x
  898. _L1_5x:
  899.     bsr.l        scosd            # operand is a DENORM
  900. _L1_6x:
  901.  
  902. #
  903. #    Result is now in FP0
  904. #
  905.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  906.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  907.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  908.     unlk        %a6
  909.     rts
  910.  
  911.  
  912. #########################################################################
  913. # MONADIC TEMPLATE                            #
  914. #########################################################################
  915.     global        _fsinhs_
  916. _fsinhs_:
  917.     link        %a6,&-LOCAL_SIZE
  918.  
  919.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  920.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  921.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  922.  
  923.     fmov.l        &0x0,%fpcr        # zero FPCR
  924.  
  925. #
  926. #    copy, convert, and tag input argument
  927. #
  928.     fmov.s        0x8(%a6),%fp0        # load sgl input
  929.     fmov.x        %fp0,FP_SRC(%a6)
  930.     lea        FP_SRC(%a6),%a0
  931.     bsr.l        tag            # fetch operand type
  932.     mov.b        %d0,STAG(%a6)
  933.     mov.b        %d0,%d1
  934.  
  935.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  936.  
  937.     clr.l        %d0
  938.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  939.  
  940.     tst.b        %d1
  941.     bne.b        _L2_2s
  942.     bsr.l        ssinh            # operand is a NORM
  943.     bra.b        _L2_6s
  944. _L2_2s:
  945.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  946.     bne.b        _L2_3s            # no
  947.     bsr.l        src_zero            # yes
  948.     bra.b        _L2_6s
  949. _L2_3s:
  950.     cmpi.b        %d1,&INF        # is operand an INF?
  951.     bne.b        _L2_4s            # no
  952.     bsr.l        src_inf            # yes
  953.     bra.b        _L2_6s
  954. _L2_4s:
  955.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  956.     bne.b        _L2_5s            # no
  957.     bsr.l        src_qnan            # yes
  958.     bra.b        _L2_6s
  959. _L2_5s:
  960.     bsr.l        ssinhd            # operand is a DENORM
  961. _L2_6s:
  962.  
  963. #
  964. #    Result is now in FP0
  965. #
  966.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  967.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  968.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  969.     unlk        %a6
  970.     rts
  971.  
  972.     global        _fsinhd_
  973. _fsinhd_:
  974.     link        %a6,&-LOCAL_SIZE
  975.  
  976.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  977.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  978.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  979.  
  980.     fmov.l        &0x0,%fpcr        # zero FPCR
  981.  
  982. #
  983. #    copy, convert, and tag input argument
  984. #
  985.     fmov.d        0x8(%a6),%fp0        # load dbl input
  986.     fmov.x        %fp0,FP_SRC(%a6)
  987.     lea        FP_SRC(%a6),%a0
  988.     bsr.l        tag            # fetch operand type
  989.     mov.b        %d0,STAG(%a6)
  990.     mov.b        %d0,%d1
  991.  
  992.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  993.  
  994.     clr.l        %d0
  995.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  996.  
  997.     mov.b        %d1,STAG(%a6)
  998.     tst.b        %d1
  999.     bne.b        _L2_2d
  1000.     bsr.l        ssinh            # operand is a NORM
  1001.     bra.b        _L2_6d
  1002. _L2_2d:
  1003.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1004.     bne.b        _L2_3d            # no
  1005.     bsr.l        src_zero            # yes
  1006.     bra.b        _L2_6d
  1007. _L2_3d:
  1008.     cmpi.b        %d1,&INF        # is operand an INF?
  1009.     bne.b        _L2_4d            # no
  1010.     bsr.l        src_inf            # yes
  1011.     bra.b        _L2_6d
  1012. _L2_4d:
  1013.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1014.     bne.b        _L2_5d            # no
  1015.     bsr.l        src_qnan            # yes
  1016.     bra.b        _L2_6d
  1017. _L2_5d:
  1018.     bsr.l        ssinhd            # operand is a DENORM
  1019. _L2_6d:
  1020.  
  1021. #
  1022. #    Result is now in FP0
  1023. #
  1024.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1025.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1026.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1027.     unlk        %a6
  1028.     rts
  1029.  
  1030.     global        _fsinhx_
  1031. _fsinhx_:
  1032.     link        %a6,&-LOCAL_SIZE
  1033.  
  1034.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1035.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1036.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1037.  
  1038.     fmov.l        &0x0,%fpcr        # zero FPCR
  1039.  
  1040. #
  1041. #    copy, convert, and tag input argument
  1042. #
  1043.     lea        FP_SRC(%a6),%a0
  1044.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  1045.     mov.l        0x8+0x4(%a6),0x4(%a0)
  1046.     mov.l        0x8+0x8(%a6),0x8(%a0)
  1047.     bsr.l        tag            # fetch operand type
  1048.     mov.b        %d0,STAG(%a6)
  1049.     mov.b        %d0,%d1
  1050.  
  1051.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1052.  
  1053.     clr.l        %d0
  1054.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1055.  
  1056.     tst.b        %d1
  1057.     bne.b        _L2_2x
  1058.     bsr.l        ssinh            # operand is a NORM
  1059.     bra.b        _L2_6x
  1060. _L2_2x:
  1061.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1062.     bne.b        _L2_3x            # no
  1063.     bsr.l        src_zero            # yes
  1064.     bra.b        _L2_6x
  1065. _L2_3x:
  1066.     cmpi.b        %d1,&INF        # is operand an INF?
  1067.     bne.b        _L2_4x            # no
  1068.     bsr.l        src_inf            # yes
  1069.     bra.b        _L2_6x
  1070. _L2_4x:
  1071.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1072.     bne.b        _L2_5x            # no
  1073.     bsr.l        src_qnan            # yes
  1074.     bra.b        _L2_6x
  1075. _L2_5x:
  1076.     bsr.l        ssinhd            # operand is a DENORM
  1077. _L2_6x:
  1078.  
  1079. #
  1080. #    Result is now in FP0
  1081. #
  1082.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1083.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1084.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1085.     unlk        %a6
  1086.     rts
  1087.  
  1088.  
  1089. #########################################################################
  1090. # MONADIC TEMPLATE                            #
  1091. #########################################################################
  1092.     global        _flognp1s_
  1093. _flognp1s_:
  1094.     link        %a6,&-LOCAL_SIZE
  1095.  
  1096.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1097.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1098.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1099.  
  1100.     fmov.l        &0x0,%fpcr        # zero FPCR
  1101.  
  1102. #
  1103. #    copy, convert, and tag input argument
  1104. #
  1105.     fmov.s        0x8(%a6),%fp0        # load sgl input
  1106.     fmov.x        %fp0,FP_SRC(%a6)
  1107.     lea        FP_SRC(%a6),%a0
  1108.     bsr.l        tag            # fetch operand type
  1109.     mov.b        %d0,STAG(%a6)
  1110.     mov.b        %d0,%d1
  1111.  
  1112.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1113.  
  1114.     clr.l        %d0
  1115.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1116.  
  1117.     tst.b        %d1
  1118.     bne.b        _L3_2s
  1119.     bsr.l        slognp1            # operand is a NORM
  1120.     bra.b        _L3_6s
  1121. _L3_2s:
  1122.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1123.     bne.b        _L3_3s            # no
  1124.     bsr.l        src_zero            # yes
  1125.     bra.b        _L3_6s
  1126. _L3_3s:
  1127.     cmpi.b        %d1,&INF        # is operand an INF?
  1128.     bne.b        _L3_4s            # no
  1129.     bsr.l        sopr_inf            # yes
  1130.     bra.b        _L3_6s
  1131. _L3_4s:
  1132.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1133.     bne.b        _L3_5s            # no
  1134.     bsr.l        src_qnan            # yes
  1135.     bra.b        _L3_6s
  1136. _L3_5s:
  1137.     bsr.l        slognp1d            # operand is a DENORM
  1138. _L3_6s:
  1139.  
  1140. #
  1141. #    Result is now in FP0
  1142. #
  1143.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1144.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1145.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1146.     unlk        %a6
  1147.     rts
  1148.  
  1149.     global        _flognp1d_
  1150. _flognp1d_:
  1151.     link        %a6,&-LOCAL_SIZE
  1152.  
  1153.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1154.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1155.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1156.  
  1157.     fmov.l        &0x0,%fpcr        # zero FPCR
  1158.  
  1159. #
  1160. #    copy, convert, and tag input argument
  1161. #
  1162.     fmov.d        0x8(%a6),%fp0        # load dbl input
  1163.     fmov.x        %fp0,FP_SRC(%a6)
  1164.     lea        FP_SRC(%a6),%a0
  1165.     bsr.l        tag            # fetch operand type
  1166.     mov.b        %d0,STAG(%a6)
  1167.     mov.b        %d0,%d1
  1168.  
  1169.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1170.  
  1171.     clr.l        %d0
  1172.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1173.  
  1174.     mov.b        %d1,STAG(%a6)
  1175.     tst.b        %d1
  1176.     bne.b        _L3_2d
  1177.     bsr.l        slognp1            # operand is a NORM
  1178.     bra.b        _L3_6d
  1179. _L3_2d:
  1180.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1181.     bne.b        _L3_3d            # no
  1182.     bsr.l        src_zero            # yes
  1183.     bra.b        _L3_6d
  1184. _L3_3d:
  1185.     cmpi.b        %d1,&INF        # is operand an INF?
  1186.     bne.b        _L3_4d            # no
  1187.     bsr.l        sopr_inf            # yes
  1188.     bra.b        _L3_6d
  1189. _L3_4d:
  1190.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1191.     bne.b        _L3_5d            # no
  1192.     bsr.l        src_qnan            # yes
  1193.     bra.b        _L3_6d
  1194. _L3_5d:
  1195.     bsr.l        slognp1d            # operand is a DENORM
  1196. _L3_6d:
  1197.  
  1198. #
  1199. #    Result is now in FP0
  1200. #
  1201.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1202.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1203.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1204.     unlk        %a6
  1205.     rts
  1206.  
  1207.     global        _flognp1x_
  1208. _flognp1x_:
  1209.     link        %a6,&-LOCAL_SIZE
  1210.  
  1211.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1212.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1213.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1214.  
  1215.     fmov.l        &0x0,%fpcr        # zero FPCR
  1216.  
  1217. #
  1218. #    copy, convert, and tag input argument
  1219. #
  1220.     lea        FP_SRC(%a6),%a0
  1221.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  1222.     mov.l        0x8+0x4(%a6),0x4(%a0)
  1223.     mov.l        0x8+0x8(%a6),0x8(%a0)
  1224.     bsr.l        tag            # fetch operand type
  1225.     mov.b        %d0,STAG(%a6)
  1226.     mov.b        %d0,%d1
  1227.  
  1228.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1229.  
  1230.     clr.l        %d0
  1231.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1232.  
  1233.     tst.b        %d1
  1234.     bne.b        _L3_2x
  1235.     bsr.l        slognp1            # operand is a NORM
  1236.     bra.b        _L3_6x
  1237. _L3_2x:
  1238.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1239.     bne.b        _L3_3x            # no
  1240.     bsr.l        src_zero            # yes
  1241.     bra.b        _L3_6x
  1242. _L3_3x:
  1243.     cmpi.b        %d1,&INF        # is operand an INF?
  1244.     bne.b        _L3_4x            # no
  1245.     bsr.l        sopr_inf            # yes
  1246.     bra.b        _L3_6x
  1247. _L3_4x:
  1248.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1249.     bne.b        _L3_5x            # no
  1250.     bsr.l        src_qnan            # yes
  1251.     bra.b        _L3_6x
  1252. _L3_5x:
  1253.     bsr.l        slognp1d            # operand is a DENORM
  1254. _L3_6x:
  1255.  
  1256. #
  1257. #    Result is now in FP0
  1258. #
  1259.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1260.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1261.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1262.     unlk        %a6
  1263.     rts
  1264.  
  1265.  
  1266. #########################################################################
  1267. # MONADIC TEMPLATE                            #
  1268. #########################################################################
  1269.     global        _fetoxm1s_
  1270. _fetoxm1s_:
  1271.     link        %a6,&-LOCAL_SIZE
  1272.  
  1273.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1274.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1275.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1276.  
  1277.     fmov.l        &0x0,%fpcr        # zero FPCR
  1278.  
  1279. #
  1280. #    copy, convert, and tag input argument
  1281. #
  1282.     fmov.s        0x8(%a6),%fp0        # load sgl input
  1283.     fmov.x        %fp0,FP_SRC(%a6)
  1284.     lea        FP_SRC(%a6),%a0
  1285.     bsr.l        tag            # fetch operand type
  1286.     mov.b        %d0,STAG(%a6)
  1287.     mov.b        %d0,%d1
  1288.  
  1289.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1290.  
  1291.     clr.l        %d0
  1292.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1293.  
  1294.     tst.b        %d1
  1295.     bne.b        _L4_2s
  1296.     bsr.l        setoxm1            # operand is a NORM
  1297.     bra.b        _L4_6s
  1298. _L4_2s:
  1299.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1300.     bne.b        _L4_3s            # no
  1301.     bsr.l        src_zero            # yes
  1302.     bra.b        _L4_6s
  1303. _L4_3s:
  1304.     cmpi.b        %d1,&INF        # is operand an INF?
  1305.     bne.b        _L4_4s            # no
  1306.     bsr.l        setoxm1i            # yes
  1307.     bra.b        _L4_6s
  1308. _L4_4s:
  1309.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1310.     bne.b        _L4_5s            # no
  1311.     bsr.l        src_qnan            # yes
  1312.     bra.b        _L4_6s
  1313. _L4_5s:
  1314.     bsr.l        setoxm1d            # operand is a DENORM
  1315. _L4_6s:
  1316.  
  1317. #
  1318. #    Result is now in FP0
  1319. #
  1320.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1321.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1322.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1323.     unlk        %a6
  1324.     rts
  1325.  
  1326.     global        _fetoxm1d_
  1327. _fetoxm1d_:
  1328.     link        %a6,&-LOCAL_SIZE
  1329.  
  1330.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1331.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1332.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1333.  
  1334.     fmov.l        &0x0,%fpcr        # zero FPCR
  1335.  
  1336. #
  1337. #    copy, convert, and tag input argument
  1338. #
  1339.     fmov.d        0x8(%a6),%fp0        # load dbl input
  1340.     fmov.x        %fp0,FP_SRC(%a6)
  1341.     lea        FP_SRC(%a6),%a0
  1342.     bsr.l        tag            # fetch operand type
  1343.     mov.b        %d0,STAG(%a6)
  1344.     mov.b        %d0,%d1
  1345.  
  1346.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1347.  
  1348.     clr.l        %d0
  1349.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1350.  
  1351.     mov.b        %d1,STAG(%a6)
  1352.     tst.b        %d1
  1353.     bne.b        _L4_2d
  1354.     bsr.l        setoxm1            # operand is a NORM
  1355.     bra.b        _L4_6d
  1356. _L4_2d:
  1357.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1358.     bne.b        _L4_3d            # no
  1359.     bsr.l        src_zero            # yes
  1360.     bra.b        _L4_6d
  1361. _L4_3d:
  1362.     cmpi.b        %d1,&INF        # is operand an INF?
  1363.     bne.b        _L4_4d            # no
  1364.     bsr.l        setoxm1i            # yes
  1365.     bra.b        _L4_6d
  1366. _L4_4d:
  1367.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1368.     bne.b        _L4_5d            # no
  1369.     bsr.l        src_qnan            # yes
  1370.     bra.b        _L4_6d
  1371. _L4_5d:
  1372.     bsr.l        setoxm1d            # operand is a DENORM
  1373. _L4_6d:
  1374.  
  1375. #
  1376. #    Result is now in FP0
  1377. #
  1378.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1379.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1380.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1381.     unlk        %a6
  1382.     rts
  1383.  
  1384.     global        _fetoxm1x_
  1385. _fetoxm1x_:
  1386.     link        %a6,&-LOCAL_SIZE
  1387.  
  1388.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1389.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1390.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1391.  
  1392.     fmov.l        &0x0,%fpcr        # zero FPCR
  1393.  
  1394. #
  1395. #    copy, convert, and tag input argument
  1396. #
  1397.     lea        FP_SRC(%a6),%a0
  1398.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  1399.     mov.l        0x8+0x4(%a6),0x4(%a0)
  1400.     mov.l        0x8+0x8(%a6),0x8(%a0)
  1401.     bsr.l        tag            # fetch operand type
  1402.     mov.b        %d0,STAG(%a6)
  1403.     mov.b        %d0,%d1
  1404.  
  1405.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1406.  
  1407.     clr.l        %d0
  1408.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1409.  
  1410.     tst.b        %d1
  1411.     bne.b        _L4_2x
  1412.     bsr.l        setoxm1            # operand is a NORM
  1413.     bra.b        _L4_6x
  1414. _L4_2x:
  1415.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1416.     bne.b        _L4_3x            # no
  1417.     bsr.l        src_zero            # yes
  1418.     bra.b        _L4_6x
  1419. _L4_3x:
  1420.     cmpi.b        %d1,&INF        # is operand an INF?
  1421.     bne.b        _L4_4x            # no
  1422.     bsr.l        setoxm1i            # yes
  1423.     bra.b        _L4_6x
  1424. _L4_4x:
  1425.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1426.     bne.b        _L4_5x            # no
  1427.     bsr.l        src_qnan            # yes
  1428.     bra.b        _L4_6x
  1429. _L4_5x:
  1430.     bsr.l        setoxm1d            # operand is a DENORM
  1431. _L4_6x:
  1432.  
  1433. #
  1434. #    Result is now in FP0
  1435. #
  1436.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1437.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1438.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1439.     unlk        %a6
  1440.     rts
  1441.  
  1442.  
  1443. #########################################################################
  1444. # MONADIC TEMPLATE                            #
  1445. #########################################################################
  1446.     global        _ftanhs_
  1447. _ftanhs_:
  1448.     link        %a6,&-LOCAL_SIZE
  1449.  
  1450.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1451.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1452.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1453.  
  1454.     fmov.l        &0x0,%fpcr        # zero FPCR
  1455.  
  1456. #
  1457. #    copy, convert, and tag input argument
  1458. #
  1459.     fmov.s        0x8(%a6),%fp0        # load sgl input
  1460.     fmov.x        %fp0,FP_SRC(%a6)
  1461.     lea        FP_SRC(%a6),%a0
  1462.     bsr.l        tag            # fetch operand type
  1463.     mov.b        %d0,STAG(%a6)
  1464.     mov.b        %d0,%d1
  1465.  
  1466.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1467.  
  1468.     clr.l        %d0
  1469.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1470.  
  1471.     tst.b        %d1
  1472.     bne.b        _L5_2s
  1473.     bsr.l        stanh            # operand is a NORM
  1474.     bra.b        _L5_6s
  1475. _L5_2s:
  1476.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1477.     bne.b        _L5_3s            # no
  1478.     bsr.l        src_zero            # yes
  1479.     bra.b        _L5_6s
  1480. _L5_3s:
  1481.     cmpi.b        %d1,&INF        # is operand an INF?
  1482.     bne.b        _L5_4s            # no
  1483.     bsr.l        src_one            # yes
  1484.     bra.b        _L5_6s
  1485. _L5_4s:
  1486.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1487.     bne.b        _L5_5s            # no
  1488.     bsr.l        src_qnan            # yes
  1489.     bra.b        _L5_6s
  1490. _L5_5s:
  1491.     bsr.l        stanhd            # operand is a DENORM
  1492. _L5_6s:
  1493.  
  1494. #
  1495. #    Result is now in FP0
  1496. #
  1497.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1498.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1499.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1500.     unlk        %a6
  1501.     rts
  1502.  
  1503.     global        _ftanhd_
  1504. _ftanhd_:
  1505.     link        %a6,&-LOCAL_SIZE
  1506.  
  1507.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1508.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1509.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1510.  
  1511.     fmov.l        &0x0,%fpcr        # zero FPCR
  1512.  
  1513. #
  1514. #    copy, convert, and tag input argument
  1515. #
  1516.     fmov.d        0x8(%a6),%fp0        # load dbl input
  1517.     fmov.x        %fp0,FP_SRC(%a6)
  1518.     lea        FP_SRC(%a6),%a0
  1519.     bsr.l        tag            # fetch operand type
  1520.     mov.b        %d0,STAG(%a6)
  1521.     mov.b        %d0,%d1
  1522.  
  1523.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1524.  
  1525.     clr.l        %d0
  1526.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1527.  
  1528.     mov.b        %d1,STAG(%a6)
  1529.     tst.b        %d1
  1530.     bne.b        _L5_2d
  1531.     bsr.l        stanh            # operand is a NORM
  1532.     bra.b        _L5_6d
  1533. _L5_2d:
  1534.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1535.     bne.b        _L5_3d            # no
  1536.     bsr.l        src_zero            # yes
  1537.     bra.b        _L5_6d
  1538. _L5_3d:
  1539.     cmpi.b        %d1,&INF        # is operand an INF?
  1540.     bne.b        _L5_4d            # no
  1541.     bsr.l        src_one            # yes
  1542.     bra.b        _L5_6d
  1543. _L5_4d:
  1544.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1545.     bne.b        _L5_5d            # no
  1546.     bsr.l        src_qnan            # yes
  1547.     bra.b        _L5_6d
  1548. _L5_5d:
  1549.     bsr.l        stanhd            # operand is a DENORM
  1550. _L5_6d:
  1551.  
  1552. #
  1553. #    Result is now in FP0
  1554. #
  1555.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1556.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1557.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1558.     unlk        %a6
  1559.     rts
  1560.  
  1561.     global        _ftanhx_
  1562. _ftanhx_:
  1563.     link        %a6,&-LOCAL_SIZE
  1564.  
  1565.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1566.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1567.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1568.  
  1569.     fmov.l        &0x0,%fpcr        # zero FPCR
  1570.  
  1571. #
  1572. #    copy, convert, and tag input argument
  1573. #
  1574.     lea        FP_SRC(%a6),%a0
  1575.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  1576.     mov.l        0x8+0x4(%a6),0x4(%a0)
  1577.     mov.l        0x8+0x8(%a6),0x8(%a0)
  1578.     bsr.l        tag            # fetch operand type
  1579.     mov.b        %d0,STAG(%a6)
  1580.     mov.b        %d0,%d1
  1581.  
  1582.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1583.  
  1584.     clr.l        %d0
  1585.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1586.  
  1587.     tst.b        %d1
  1588.     bne.b        _L5_2x
  1589.     bsr.l        stanh            # operand is a NORM
  1590.     bra.b        _L5_6x
  1591. _L5_2x:
  1592.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1593.     bne.b        _L5_3x            # no
  1594.     bsr.l        src_zero            # yes
  1595.     bra.b        _L5_6x
  1596. _L5_3x:
  1597.     cmpi.b        %d1,&INF        # is operand an INF?
  1598.     bne.b        _L5_4x            # no
  1599.     bsr.l        src_one            # yes
  1600.     bra.b        _L5_6x
  1601. _L5_4x:
  1602.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1603.     bne.b        _L5_5x            # no
  1604.     bsr.l        src_qnan            # yes
  1605.     bra.b        _L5_6x
  1606. _L5_5x:
  1607.     bsr.l        stanhd            # operand is a DENORM
  1608. _L5_6x:
  1609.  
  1610. #
  1611. #    Result is now in FP0
  1612. #
  1613.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1614.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1615.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1616.     unlk        %a6
  1617.     rts
  1618.  
  1619.  
  1620. #########################################################################
  1621. # MONADIC TEMPLATE                            #
  1622. #########################################################################
  1623.     global        _fatans_
  1624. _fatans_:
  1625.     link        %a6,&-LOCAL_SIZE
  1626.  
  1627.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1628.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1629.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1630.  
  1631.     fmov.l        &0x0,%fpcr        # zero FPCR
  1632.  
  1633. #
  1634. #    copy, convert, and tag input argument
  1635. #
  1636.     fmov.s        0x8(%a6),%fp0        # load sgl input
  1637.     fmov.x        %fp0,FP_SRC(%a6)
  1638.     lea        FP_SRC(%a6),%a0
  1639.     bsr.l        tag            # fetch operand type
  1640.     mov.b        %d0,STAG(%a6)
  1641.     mov.b        %d0,%d1
  1642.  
  1643.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1644.  
  1645.     clr.l        %d0
  1646.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1647.  
  1648.     tst.b        %d1
  1649.     bne.b        _L6_2s
  1650.     bsr.l        satan            # operand is a NORM
  1651.     bra.b        _L6_6s
  1652. _L6_2s:
  1653.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1654.     bne.b        _L6_3s            # no
  1655.     bsr.l        src_zero            # yes
  1656.     bra.b        _L6_6s
  1657. _L6_3s:
  1658.     cmpi.b        %d1,&INF        # is operand an INF?
  1659.     bne.b        _L6_4s            # no
  1660.     bsr.l        spi_2            # yes
  1661.     bra.b        _L6_6s
  1662. _L6_4s:
  1663.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1664.     bne.b        _L6_5s            # no
  1665.     bsr.l        src_qnan            # yes
  1666.     bra.b        _L6_6s
  1667. _L6_5s:
  1668.     bsr.l        satand            # operand is a DENORM
  1669. _L6_6s:
  1670.  
  1671. #
  1672. #    Result is now in FP0
  1673. #
  1674.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1675.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1676.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1677.     unlk        %a6
  1678.     rts
  1679.  
  1680.     global        _fatand_
  1681. _fatand_:
  1682.     link        %a6,&-LOCAL_SIZE
  1683.  
  1684.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1685.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1686.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1687.  
  1688.     fmov.l        &0x0,%fpcr        # zero FPCR
  1689.  
  1690. #
  1691. #    copy, convert, and tag input argument
  1692. #
  1693.     fmov.d        0x8(%a6),%fp0        # load dbl input
  1694.     fmov.x        %fp0,FP_SRC(%a6)
  1695.     lea        FP_SRC(%a6),%a0
  1696.     bsr.l        tag            # fetch operand type
  1697.     mov.b        %d0,STAG(%a6)
  1698.     mov.b        %d0,%d1
  1699.  
  1700.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1701.  
  1702.     clr.l        %d0
  1703.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1704.  
  1705.     mov.b        %d1,STAG(%a6)
  1706.     tst.b        %d1
  1707.     bne.b        _L6_2d
  1708.     bsr.l        satan            # operand is a NORM
  1709.     bra.b        _L6_6d
  1710. _L6_2d:
  1711.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1712.     bne.b        _L6_3d            # no
  1713.     bsr.l        src_zero            # yes
  1714.     bra.b        _L6_6d
  1715. _L6_3d:
  1716.     cmpi.b        %d1,&INF        # is operand an INF?
  1717.     bne.b        _L6_4d            # no
  1718.     bsr.l        spi_2            # yes
  1719.     bra.b        _L6_6d
  1720. _L6_4d:
  1721.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1722.     bne.b        _L6_5d            # no
  1723.     bsr.l        src_qnan            # yes
  1724.     bra.b        _L6_6d
  1725. _L6_5d:
  1726.     bsr.l        satand            # operand is a DENORM
  1727. _L6_6d:
  1728.  
  1729. #
  1730. #    Result is now in FP0
  1731. #
  1732.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1733.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1734.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1735.     unlk        %a6
  1736.     rts
  1737.  
  1738.     global        _fatanx_
  1739. _fatanx_:
  1740.     link        %a6,&-LOCAL_SIZE
  1741.  
  1742.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1743.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1744.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1745.  
  1746.     fmov.l        &0x0,%fpcr        # zero FPCR
  1747.  
  1748. #
  1749. #    copy, convert, and tag input argument
  1750. #
  1751.     lea        FP_SRC(%a6),%a0
  1752.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  1753.     mov.l        0x8+0x4(%a6),0x4(%a0)
  1754.     mov.l        0x8+0x8(%a6),0x8(%a0)
  1755.     bsr.l        tag            # fetch operand type
  1756.     mov.b        %d0,STAG(%a6)
  1757.     mov.b        %d0,%d1
  1758.  
  1759.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1760.  
  1761.     clr.l        %d0
  1762.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1763.  
  1764.     tst.b        %d1
  1765.     bne.b        _L6_2x
  1766.     bsr.l        satan            # operand is a NORM
  1767.     bra.b        _L6_6x
  1768. _L6_2x:
  1769.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1770.     bne.b        _L6_3x            # no
  1771.     bsr.l        src_zero            # yes
  1772.     bra.b        _L6_6x
  1773. _L6_3x:
  1774.     cmpi.b        %d1,&INF        # is operand an INF?
  1775.     bne.b        _L6_4x            # no
  1776.     bsr.l        spi_2            # yes
  1777.     bra.b        _L6_6x
  1778. _L6_4x:
  1779.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1780.     bne.b        _L6_5x            # no
  1781.     bsr.l        src_qnan            # yes
  1782.     bra.b        _L6_6x
  1783. _L6_5x:
  1784.     bsr.l        satand            # operand is a DENORM
  1785. _L6_6x:
  1786.  
  1787. #
  1788. #    Result is now in FP0
  1789. #
  1790.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1791.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1792.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1793.     unlk        %a6
  1794.     rts
  1795.  
  1796.  
  1797. #########################################################################
  1798. # MONADIC TEMPLATE                            #
  1799. #########################################################################
  1800.     global        _fasins_
  1801. _fasins_:
  1802.     link        %a6,&-LOCAL_SIZE
  1803.  
  1804.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1805.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1806.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1807.  
  1808.     fmov.l        &0x0,%fpcr        # zero FPCR
  1809.  
  1810. #
  1811. #    copy, convert, and tag input argument
  1812. #
  1813.     fmov.s        0x8(%a6),%fp0        # load sgl input
  1814.     fmov.x        %fp0,FP_SRC(%a6)
  1815.     lea        FP_SRC(%a6),%a0
  1816.     bsr.l        tag            # fetch operand type
  1817.     mov.b        %d0,STAG(%a6)
  1818.     mov.b        %d0,%d1
  1819.  
  1820.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1821.  
  1822.     clr.l        %d0
  1823.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1824.  
  1825.     tst.b        %d1
  1826.     bne.b        _L7_2s
  1827.     bsr.l        sasin            # operand is a NORM
  1828.     bra.b        _L7_6s
  1829. _L7_2s:
  1830.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1831.     bne.b        _L7_3s            # no
  1832.     bsr.l        src_zero            # yes
  1833.     bra.b        _L7_6s
  1834. _L7_3s:
  1835.     cmpi.b        %d1,&INF        # is operand an INF?
  1836.     bne.b        _L7_4s            # no
  1837.     bsr.l        t_operr            # yes
  1838.     bra.b        _L7_6s
  1839. _L7_4s:
  1840.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1841.     bne.b        _L7_5s            # no
  1842.     bsr.l        src_qnan            # yes
  1843.     bra.b        _L7_6s
  1844. _L7_5s:
  1845.     bsr.l        sasind            # operand is a DENORM
  1846. _L7_6s:
  1847.  
  1848. #
  1849. #    Result is now in FP0
  1850. #
  1851.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1852.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1853.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1854.     unlk        %a6
  1855.     rts
  1856.  
  1857.     global        _fasind_
  1858. _fasind_:
  1859.     link        %a6,&-LOCAL_SIZE
  1860.  
  1861.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1862.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1863.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1864.  
  1865.     fmov.l        &0x0,%fpcr        # zero FPCR
  1866.  
  1867. #
  1868. #    copy, convert, and tag input argument
  1869. #
  1870.     fmov.d        0x8(%a6),%fp0        # load dbl input
  1871.     fmov.x        %fp0,FP_SRC(%a6)
  1872.     lea        FP_SRC(%a6),%a0
  1873.     bsr.l        tag            # fetch operand type
  1874.     mov.b        %d0,STAG(%a6)
  1875.     mov.b        %d0,%d1
  1876.  
  1877.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1878.  
  1879.     clr.l        %d0
  1880.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1881.  
  1882.     mov.b        %d1,STAG(%a6)
  1883.     tst.b        %d1
  1884.     bne.b        _L7_2d
  1885.     bsr.l        sasin            # operand is a NORM
  1886.     bra.b        _L7_6d
  1887. _L7_2d:
  1888.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1889.     bne.b        _L7_3d            # no
  1890.     bsr.l        src_zero            # yes
  1891.     bra.b        _L7_6d
  1892. _L7_3d:
  1893.     cmpi.b        %d1,&INF        # is operand an INF?
  1894.     bne.b        _L7_4d            # no
  1895.     bsr.l        t_operr            # yes
  1896.     bra.b        _L7_6d
  1897. _L7_4d:
  1898.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1899.     bne.b        _L7_5d            # no
  1900.     bsr.l        src_qnan            # yes
  1901.     bra.b        _L7_6d
  1902. _L7_5d:
  1903.     bsr.l        sasind            # operand is a DENORM
  1904. _L7_6d:
  1905.  
  1906. #
  1907. #    Result is now in FP0
  1908. #
  1909.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1910.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1911.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1912.     unlk        %a6
  1913.     rts
  1914.  
  1915.     global        _fasinx_
  1916. _fasinx_:
  1917.     link        %a6,&-LOCAL_SIZE
  1918.  
  1919.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1920.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1921.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1922.  
  1923.     fmov.l        &0x0,%fpcr        # zero FPCR
  1924.  
  1925. #
  1926. #    copy, convert, and tag input argument
  1927. #
  1928.     lea        FP_SRC(%a6),%a0
  1929.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  1930.     mov.l        0x8+0x4(%a6),0x4(%a0)
  1931.     mov.l        0x8+0x8(%a6),0x8(%a0)
  1932.     bsr.l        tag            # fetch operand type
  1933.     mov.b        %d0,STAG(%a6)
  1934.     mov.b        %d0,%d1
  1935.  
  1936.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1937.  
  1938.     clr.l        %d0
  1939.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  1940.  
  1941.     tst.b        %d1
  1942.     bne.b        _L7_2x
  1943.     bsr.l        sasin            # operand is a NORM
  1944.     bra.b        _L7_6x
  1945. _L7_2x:
  1946.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  1947.     bne.b        _L7_3x            # no
  1948.     bsr.l        src_zero            # yes
  1949.     bra.b        _L7_6x
  1950. _L7_3x:
  1951.     cmpi.b        %d1,&INF        # is operand an INF?
  1952.     bne.b        _L7_4x            # no
  1953.     bsr.l        t_operr            # yes
  1954.     bra.b        _L7_6x
  1955. _L7_4x:
  1956.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  1957.     bne.b        _L7_5x            # no
  1958.     bsr.l        src_qnan            # yes
  1959.     bra.b        _L7_6x
  1960. _L7_5x:
  1961.     bsr.l        sasind            # operand is a DENORM
  1962. _L7_6x:
  1963.  
  1964. #
  1965. #    Result is now in FP0
  1966. #
  1967.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  1968.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  1969.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  1970.     unlk        %a6
  1971.     rts
  1972.  
  1973.  
  1974. #########################################################################
  1975. # MONADIC TEMPLATE                            #
  1976. #########################################################################
  1977.     global        _fatanhs_
  1978. _fatanhs_:
  1979.     link        %a6,&-LOCAL_SIZE
  1980.  
  1981.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  1982.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  1983.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  1984.  
  1985.     fmov.l        &0x0,%fpcr        # zero FPCR
  1986.  
  1987. #
  1988. #    copy, convert, and tag input argument
  1989. #
  1990.     fmov.s        0x8(%a6),%fp0        # load sgl input
  1991.     fmov.x        %fp0,FP_SRC(%a6)
  1992.     lea        FP_SRC(%a6),%a0
  1993.     bsr.l        tag            # fetch operand type
  1994.     mov.b        %d0,STAG(%a6)
  1995.     mov.b        %d0,%d1
  1996.  
  1997.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  1998.  
  1999.     clr.l        %d0
  2000.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2001.  
  2002.     tst.b        %d1
  2003.     bne.b        _L8_2s
  2004.     bsr.l        satanh            # operand is a NORM
  2005.     bra.b        _L8_6s
  2006. _L8_2s:
  2007.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2008.     bne.b        _L8_3s            # no
  2009.     bsr.l        src_zero            # yes
  2010.     bra.b        _L8_6s
  2011. _L8_3s:
  2012.     cmpi.b        %d1,&INF        # is operand an INF?
  2013.     bne.b        _L8_4s            # no
  2014.     bsr.l        t_operr            # yes
  2015.     bra.b        _L8_6s
  2016. _L8_4s:
  2017.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2018.     bne.b        _L8_5s            # no
  2019.     bsr.l        src_qnan            # yes
  2020.     bra.b        _L8_6s
  2021. _L8_5s:
  2022.     bsr.l        satanhd            # operand is a DENORM
  2023. _L8_6s:
  2024.  
  2025. #
  2026. #    Result is now in FP0
  2027. #
  2028.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2029.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2030.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2031.     unlk        %a6
  2032.     rts
  2033.  
  2034.     global        _fatanhd_
  2035. _fatanhd_:
  2036.     link        %a6,&-LOCAL_SIZE
  2037.  
  2038.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2039.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2040.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2041.  
  2042.     fmov.l        &0x0,%fpcr        # zero FPCR
  2043.  
  2044. #
  2045. #    copy, convert, and tag input argument
  2046. #
  2047.     fmov.d        0x8(%a6),%fp0        # load dbl input
  2048.     fmov.x        %fp0,FP_SRC(%a6)
  2049.     lea        FP_SRC(%a6),%a0
  2050.     bsr.l        tag            # fetch operand type
  2051.     mov.b        %d0,STAG(%a6)
  2052.     mov.b        %d0,%d1
  2053.  
  2054.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2055.  
  2056.     clr.l        %d0
  2057.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2058.  
  2059.     mov.b        %d1,STAG(%a6)
  2060.     tst.b        %d1
  2061.     bne.b        _L8_2d
  2062.     bsr.l        satanh            # operand is a NORM
  2063.     bra.b        _L8_6d
  2064. _L8_2d:
  2065.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2066.     bne.b        _L8_3d            # no
  2067.     bsr.l        src_zero            # yes
  2068.     bra.b        _L8_6d
  2069. _L8_3d:
  2070.     cmpi.b        %d1,&INF        # is operand an INF?
  2071.     bne.b        _L8_4d            # no
  2072.     bsr.l        t_operr            # yes
  2073.     bra.b        _L8_6d
  2074. _L8_4d:
  2075.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2076.     bne.b        _L8_5d            # no
  2077.     bsr.l        src_qnan            # yes
  2078.     bra.b        _L8_6d
  2079. _L8_5d:
  2080.     bsr.l        satanhd            # operand is a DENORM
  2081. _L8_6d:
  2082.  
  2083. #
  2084. #    Result is now in FP0
  2085. #
  2086.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2087.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2088.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2089.     unlk        %a6
  2090.     rts
  2091.  
  2092.     global        _fatanhx_
  2093. _fatanhx_:
  2094.     link        %a6,&-LOCAL_SIZE
  2095.  
  2096.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2097.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2098.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2099.  
  2100.     fmov.l        &0x0,%fpcr        # zero FPCR
  2101.  
  2102. #
  2103. #    copy, convert, and tag input argument
  2104. #
  2105.     lea        FP_SRC(%a6),%a0
  2106.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  2107.     mov.l        0x8+0x4(%a6),0x4(%a0)
  2108.     mov.l        0x8+0x8(%a6),0x8(%a0)
  2109.     bsr.l        tag            # fetch operand type
  2110.     mov.b        %d0,STAG(%a6)
  2111.     mov.b        %d0,%d1
  2112.  
  2113.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2114.  
  2115.     clr.l        %d0
  2116.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2117.  
  2118.     tst.b        %d1
  2119.     bne.b        _L8_2x
  2120.     bsr.l        satanh            # operand is a NORM
  2121.     bra.b        _L8_6x
  2122. _L8_2x:
  2123.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2124.     bne.b        _L8_3x            # no
  2125.     bsr.l        src_zero            # yes
  2126.     bra.b        _L8_6x
  2127. _L8_3x:
  2128.     cmpi.b        %d1,&INF        # is operand an INF?
  2129.     bne.b        _L8_4x            # no
  2130.     bsr.l        t_operr            # yes
  2131.     bra.b        _L8_6x
  2132. _L8_4x:
  2133.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2134.     bne.b        _L8_5x            # no
  2135.     bsr.l        src_qnan            # yes
  2136.     bra.b        _L8_6x
  2137. _L8_5x:
  2138.     bsr.l        satanhd            # operand is a DENORM
  2139. _L8_6x:
  2140.  
  2141. #
  2142. #    Result is now in FP0
  2143. #
  2144.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2145.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2146.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2147.     unlk        %a6
  2148.     rts
  2149.  
  2150.  
  2151. #########################################################################
  2152. # MONADIC TEMPLATE                            #
  2153. #########################################################################
  2154.     global        _ftans_
  2155. _ftans_:
  2156.     link        %a6,&-LOCAL_SIZE
  2157.  
  2158.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2159.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2160.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2161.  
  2162.     fmov.l        &0x0,%fpcr        # zero FPCR
  2163.  
  2164. #
  2165. #    copy, convert, and tag input argument
  2166. #
  2167.     fmov.s        0x8(%a6),%fp0        # load sgl input
  2168.     fmov.x        %fp0,FP_SRC(%a6)
  2169.     lea        FP_SRC(%a6),%a0
  2170.     bsr.l        tag            # fetch operand type
  2171.     mov.b        %d0,STAG(%a6)
  2172.     mov.b        %d0,%d1
  2173.  
  2174.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2175.  
  2176.     clr.l        %d0
  2177.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2178.  
  2179.     tst.b        %d1
  2180.     bne.b        _L9_2s
  2181.     bsr.l        stan            # operand is a NORM
  2182.     bra.b        _L9_6s
  2183. _L9_2s:
  2184.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2185.     bne.b        _L9_3s            # no
  2186.     bsr.l        src_zero            # yes
  2187.     bra.b        _L9_6s
  2188. _L9_3s:
  2189.     cmpi.b        %d1,&INF        # is operand an INF?
  2190.     bne.b        _L9_4s            # no
  2191.     bsr.l        t_operr            # yes
  2192.     bra.b        _L9_6s
  2193. _L9_4s:
  2194.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2195.     bne.b        _L9_5s            # no
  2196.     bsr.l        src_qnan            # yes
  2197.     bra.b        _L9_6s
  2198. _L9_5s:
  2199.     bsr.l        stand            # operand is a DENORM
  2200. _L9_6s:
  2201.  
  2202. #
  2203. #    Result is now in FP0
  2204. #
  2205.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2206.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2207.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2208.     unlk        %a6
  2209.     rts
  2210.  
  2211.     global        _ftand_
  2212. _ftand_:
  2213.     link        %a6,&-LOCAL_SIZE
  2214.  
  2215.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2216.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2217.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2218.  
  2219.     fmov.l        &0x0,%fpcr        # zero FPCR
  2220.  
  2221. #
  2222. #    copy, convert, and tag input argument
  2223. #
  2224.     fmov.d        0x8(%a6),%fp0        # load dbl input
  2225.     fmov.x        %fp0,FP_SRC(%a6)
  2226.     lea        FP_SRC(%a6),%a0
  2227.     bsr.l        tag            # fetch operand type
  2228.     mov.b        %d0,STAG(%a6)
  2229.     mov.b        %d0,%d1
  2230.  
  2231.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2232.  
  2233.     clr.l        %d0
  2234.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2235.  
  2236.     mov.b        %d1,STAG(%a6)
  2237.     tst.b        %d1
  2238.     bne.b        _L9_2d
  2239.     bsr.l        stan            # operand is a NORM
  2240.     bra.b        _L9_6d
  2241. _L9_2d:
  2242.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2243.     bne.b        _L9_3d            # no
  2244.     bsr.l        src_zero            # yes
  2245.     bra.b        _L9_6d
  2246. _L9_3d:
  2247.     cmpi.b        %d1,&INF        # is operand an INF?
  2248.     bne.b        _L9_4d            # no
  2249.     bsr.l        t_operr            # yes
  2250.     bra.b        _L9_6d
  2251. _L9_4d:
  2252.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2253.     bne.b        _L9_5d            # no
  2254.     bsr.l        src_qnan            # yes
  2255.     bra.b        _L9_6d
  2256. _L9_5d:
  2257.     bsr.l        stand            # operand is a DENORM
  2258. _L9_6d:
  2259.  
  2260. #
  2261. #    Result is now in FP0
  2262. #
  2263.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2264.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2265.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2266.     unlk        %a6
  2267.     rts
  2268.  
  2269.     global        _ftanx_
  2270. _ftanx_:
  2271.     link        %a6,&-LOCAL_SIZE
  2272.  
  2273.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2274.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2275.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2276.  
  2277.     fmov.l        &0x0,%fpcr        # zero FPCR
  2278.  
  2279. #
  2280. #    copy, convert, and tag input argument
  2281. #
  2282.     lea        FP_SRC(%a6),%a0
  2283.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  2284.     mov.l        0x8+0x4(%a6),0x4(%a0)
  2285.     mov.l        0x8+0x8(%a6),0x8(%a0)
  2286.     bsr.l        tag            # fetch operand type
  2287.     mov.b        %d0,STAG(%a6)
  2288.     mov.b        %d0,%d1
  2289.  
  2290.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2291.  
  2292.     clr.l        %d0
  2293.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2294.  
  2295.     tst.b        %d1
  2296.     bne.b        _L9_2x
  2297.     bsr.l        stan            # operand is a NORM
  2298.     bra.b        _L9_6x
  2299. _L9_2x:
  2300.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2301.     bne.b        _L9_3x            # no
  2302.     bsr.l        src_zero            # yes
  2303.     bra.b        _L9_6x
  2304. _L9_3x:
  2305.     cmpi.b        %d1,&INF        # is operand an INF?
  2306.     bne.b        _L9_4x            # no
  2307.     bsr.l        t_operr            # yes
  2308.     bra.b        _L9_6x
  2309. _L9_4x:
  2310.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2311.     bne.b        _L9_5x            # no
  2312.     bsr.l        src_qnan            # yes
  2313.     bra.b        _L9_6x
  2314. _L9_5x:
  2315.     bsr.l        stand            # operand is a DENORM
  2316. _L9_6x:
  2317.  
  2318. #
  2319. #    Result is now in FP0
  2320. #
  2321.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2322.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2323.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2324.     unlk        %a6
  2325.     rts
  2326.  
  2327.  
  2328. #########################################################################
  2329. # MONADIC TEMPLATE                            #
  2330. #########################################################################
  2331.     global        _fetoxs_
  2332. _fetoxs_:
  2333.     link        %a6,&-LOCAL_SIZE
  2334.  
  2335.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2336.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2337.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2338.  
  2339.     fmov.l        &0x0,%fpcr        # zero FPCR
  2340.  
  2341. #
  2342. #    copy, convert, and tag input argument
  2343. #
  2344.     fmov.s        0x8(%a6),%fp0        # load sgl input
  2345.     fmov.x        %fp0,FP_SRC(%a6)
  2346.     lea        FP_SRC(%a6),%a0
  2347.     bsr.l        tag            # fetch operand type
  2348.     mov.b        %d0,STAG(%a6)
  2349.     mov.b        %d0,%d1
  2350.  
  2351.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2352.  
  2353.     clr.l        %d0
  2354.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2355.  
  2356.     tst.b        %d1
  2357.     bne.b        _L10_2s
  2358.     bsr.l        setox            # operand is a NORM
  2359.     bra.b        _L10_6s
  2360. _L10_2s:
  2361.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2362.     bne.b        _L10_3s            # no
  2363.     bsr.l        ld_pone            # yes
  2364.     bra.b        _L10_6s
  2365. _L10_3s:
  2366.     cmpi.b        %d1,&INF        # is operand an INF?
  2367.     bne.b        _L10_4s            # no
  2368.     bsr.l        szr_inf            # yes
  2369.     bra.b        _L10_6s
  2370. _L10_4s:
  2371.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2372.     bne.b        _L10_5s            # no
  2373.     bsr.l        src_qnan            # yes
  2374.     bra.b        _L10_6s
  2375. _L10_5s:
  2376.     bsr.l        setoxd            # operand is a DENORM
  2377. _L10_6s:
  2378.  
  2379. #
  2380. #    Result is now in FP0
  2381. #
  2382.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2383.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2384.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2385.     unlk        %a6
  2386.     rts
  2387.  
  2388.     global        _fetoxd_
  2389. _fetoxd_:
  2390.     link        %a6,&-LOCAL_SIZE
  2391.  
  2392.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2393.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2394.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2395.  
  2396.     fmov.l        &0x0,%fpcr        # zero FPCR
  2397.  
  2398. #
  2399. #    copy, convert, and tag input argument
  2400. #
  2401.     fmov.d        0x8(%a6),%fp0        # load dbl input
  2402.     fmov.x        %fp0,FP_SRC(%a6)
  2403.     lea        FP_SRC(%a6),%a0
  2404.     bsr.l        tag            # fetch operand type
  2405.     mov.b        %d0,STAG(%a6)
  2406.     mov.b        %d0,%d1
  2407.  
  2408.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2409.  
  2410.     clr.l        %d0
  2411.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2412.  
  2413.     mov.b        %d1,STAG(%a6)
  2414.     tst.b        %d1
  2415.     bne.b        _L10_2d
  2416.     bsr.l        setox            # operand is a NORM
  2417.     bra.b        _L10_6d
  2418. _L10_2d:
  2419.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2420.     bne.b        _L10_3d            # no
  2421.     bsr.l        ld_pone            # yes
  2422.     bra.b        _L10_6d
  2423. _L10_3d:
  2424.     cmpi.b        %d1,&INF        # is operand an INF?
  2425.     bne.b        _L10_4d            # no
  2426.     bsr.l        szr_inf            # yes
  2427.     bra.b        _L10_6d
  2428. _L10_4d:
  2429.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2430.     bne.b        _L10_5d            # no
  2431.     bsr.l        src_qnan            # yes
  2432.     bra.b        _L10_6d
  2433. _L10_5d:
  2434.     bsr.l        setoxd            # operand is a DENORM
  2435. _L10_6d:
  2436.  
  2437. #
  2438. #    Result is now in FP0
  2439. #
  2440.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2441.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2442.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2443.     unlk        %a6
  2444.     rts
  2445.  
  2446.     global        _fetoxx_
  2447. _fetoxx_:
  2448.     link        %a6,&-LOCAL_SIZE
  2449.  
  2450.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2451.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2452.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2453.  
  2454.     fmov.l        &0x0,%fpcr        # zero FPCR
  2455.  
  2456. #
  2457. #    copy, convert, and tag input argument
  2458. #
  2459.     lea        FP_SRC(%a6),%a0
  2460.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  2461.     mov.l        0x8+0x4(%a6),0x4(%a0)
  2462.     mov.l        0x8+0x8(%a6),0x8(%a0)
  2463.     bsr.l        tag            # fetch operand type
  2464.     mov.b        %d0,STAG(%a6)
  2465.     mov.b        %d0,%d1
  2466.  
  2467.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2468.  
  2469.     clr.l        %d0
  2470.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2471.  
  2472.     tst.b        %d1
  2473.     bne.b        _L10_2x
  2474.     bsr.l        setox            # operand is a NORM
  2475.     bra.b        _L10_6x
  2476. _L10_2x:
  2477.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2478.     bne.b        _L10_3x            # no
  2479.     bsr.l        ld_pone            # yes
  2480.     bra.b        _L10_6x
  2481. _L10_3x:
  2482.     cmpi.b        %d1,&INF        # is operand an INF?
  2483.     bne.b        _L10_4x            # no
  2484.     bsr.l        szr_inf            # yes
  2485.     bra.b        _L10_6x
  2486. _L10_4x:
  2487.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2488.     bne.b        _L10_5x            # no
  2489.     bsr.l        src_qnan            # yes
  2490.     bra.b        _L10_6x
  2491. _L10_5x:
  2492.     bsr.l        setoxd            # operand is a DENORM
  2493. _L10_6x:
  2494.  
  2495. #
  2496. #    Result is now in FP0
  2497. #
  2498.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2499.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2500.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2501.     unlk        %a6
  2502.     rts
  2503.  
  2504.  
  2505. #########################################################################
  2506. # MONADIC TEMPLATE                            #
  2507. #########################################################################
  2508.     global        _ftwotoxs_
  2509. _ftwotoxs_:
  2510.     link        %a6,&-LOCAL_SIZE
  2511.  
  2512.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2513.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2514.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2515.  
  2516.     fmov.l        &0x0,%fpcr        # zero FPCR
  2517.  
  2518. #
  2519. #    copy, convert, and tag input argument
  2520. #
  2521.     fmov.s        0x8(%a6),%fp0        # load sgl input
  2522.     fmov.x        %fp0,FP_SRC(%a6)
  2523.     lea        FP_SRC(%a6),%a0
  2524.     bsr.l        tag            # fetch operand type
  2525.     mov.b        %d0,STAG(%a6)
  2526.     mov.b        %d0,%d1
  2527.  
  2528.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2529.  
  2530.     clr.l        %d0
  2531.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2532.  
  2533.     tst.b        %d1
  2534.     bne.b        _L11_2s
  2535.     bsr.l        stwotox            # operand is a NORM
  2536.     bra.b        _L11_6s
  2537. _L11_2s:
  2538.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2539.     bne.b        _L11_3s            # no
  2540.     bsr.l        ld_pone            # yes
  2541.     bra.b        _L11_6s
  2542. _L11_3s:
  2543.     cmpi.b        %d1,&INF        # is operand an INF?
  2544.     bne.b        _L11_4s            # no
  2545.     bsr.l        szr_inf            # yes
  2546.     bra.b        _L11_6s
  2547. _L11_4s:
  2548.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2549.     bne.b        _L11_5s            # no
  2550.     bsr.l        src_qnan            # yes
  2551.     bra.b        _L11_6s
  2552. _L11_5s:
  2553.     bsr.l        stwotoxd            # operand is a DENORM
  2554. _L11_6s:
  2555.  
  2556. #
  2557. #    Result is now in FP0
  2558. #
  2559.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2560.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2561.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2562.     unlk        %a6
  2563.     rts
  2564.  
  2565.     global        _ftwotoxd_
  2566. _ftwotoxd_:
  2567.     link        %a6,&-LOCAL_SIZE
  2568.  
  2569.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2570.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2571.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2572.  
  2573.     fmov.l        &0x0,%fpcr        # zero FPCR
  2574.  
  2575. #
  2576. #    copy, convert, and tag input argument
  2577. #
  2578.     fmov.d        0x8(%a6),%fp0        # load dbl input
  2579.     fmov.x        %fp0,FP_SRC(%a6)
  2580.     lea        FP_SRC(%a6),%a0
  2581.     bsr.l        tag            # fetch operand type
  2582.     mov.b        %d0,STAG(%a6)
  2583.     mov.b        %d0,%d1
  2584.  
  2585.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2586.  
  2587.     clr.l        %d0
  2588.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2589.  
  2590.     mov.b        %d1,STAG(%a6)
  2591.     tst.b        %d1
  2592.     bne.b        _L11_2d
  2593.     bsr.l        stwotox            # operand is a NORM
  2594.     bra.b        _L11_6d
  2595. _L11_2d:
  2596.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2597.     bne.b        _L11_3d            # no
  2598.     bsr.l        ld_pone            # yes
  2599.     bra.b        _L11_6d
  2600. _L11_3d:
  2601.     cmpi.b        %d1,&INF        # is operand an INF?
  2602.     bne.b        _L11_4d            # no
  2603.     bsr.l        szr_inf            # yes
  2604.     bra.b        _L11_6d
  2605. _L11_4d:
  2606.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2607.     bne.b        _L11_5d            # no
  2608.     bsr.l        src_qnan            # yes
  2609.     bra.b        _L11_6d
  2610. _L11_5d:
  2611.     bsr.l        stwotoxd            # operand is a DENORM
  2612. _L11_6d:
  2613.  
  2614. #
  2615. #    Result is now in FP0
  2616. #
  2617.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2618.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2619.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2620.     unlk        %a6
  2621.     rts
  2622.  
  2623.     global        _ftwotoxx_
  2624. _ftwotoxx_:
  2625.     link        %a6,&-LOCAL_SIZE
  2626.  
  2627.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2628.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2629.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2630.  
  2631.     fmov.l        &0x0,%fpcr        # zero FPCR
  2632.  
  2633. #
  2634. #    copy, convert, and tag input argument
  2635. #
  2636.     lea        FP_SRC(%a6),%a0
  2637.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  2638.     mov.l        0x8+0x4(%a6),0x4(%a0)
  2639.     mov.l        0x8+0x8(%a6),0x8(%a0)
  2640.     bsr.l        tag            # fetch operand type
  2641.     mov.b        %d0,STAG(%a6)
  2642.     mov.b        %d0,%d1
  2643.  
  2644.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2645.  
  2646.     clr.l        %d0
  2647.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2648.  
  2649.     tst.b        %d1
  2650.     bne.b        _L11_2x
  2651.     bsr.l        stwotox            # operand is a NORM
  2652.     bra.b        _L11_6x
  2653. _L11_2x:
  2654.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2655.     bne.b        _L11_3x            # no
  2656.     bsr.l        ld_pone            # yes
  2657.     bra.b        _L11_6x
  2658. _L11_3x:
  2659.     cmpi.b        %d1,&INF        # is operand an INF?
  2660.     bne.b        _L11_4x            # no
  2661.     bsr.l        szr_inf            # yes
  2662.     bra.b        _L11_6x
  2663. _L11_4x:
  2664.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2665.     bne.b        _L11_5x            # no
  2666.     bsr.l        src_qnan            # yes
  2667.     bra.b        _L11_6x
  2668. _L11_5x:
  2669.     bsr.l        stwotoxd            # operand is a DENORM
  2670. _L11_6x:
  2671.  
  2672. #
  2673. #    Result is now in FP0
  2674. #
  2675.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2676.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2677.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2678.     unlk        %a6
  2679.     rts
  2680.  
  2681.  
  2682. #########################################################################
  2683. # MONADIC TEMPLATE                            #
  2684. #########################################################################
  2685.     global        _ftentoxs_
  2686. _ftentoxs_:
  2687.     link        %a6,&-LOCAL_SIZE
  2688.  
  2689.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2690.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2691.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2692.  
  2693.     fmov.l        &0x0,%fpcr        # zero FPCR
  2694.  
  2695. #
  2696. #    copy, convert, and tag input argument
  2697. #
  2698.     fmov.s        0x8(%a6),%fp0        # load sgl input
  2699.     fmov.x        %fp0,FP_SRC(%a6)
  2700.     lea        FP_SRC(%a6),%a0
  2701.     bsr.l        tag            # fetch operand type
  2702.     mov.b        %d0,STAG(%a6)
  2703.     mov.b        %d0,%d1
  2704.  
  2705.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2706.  
  2707.     clr.l        %d0
  2708.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2709.  
  2710.     tst.b        %d1
  2711.     bne.b        _L12_2s
  2712.     bsr.l        stentox            # operand is a NORM
  2713.     bra.b        _L12_6s
  2714. _L12_2s:
  2715.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2716.     bne.b        _L12_3s            # no
  2717.     bsr.l        ld_pone            # yes
  2718.     bra.b        _L12_6s
  2719. _L12_3s:
  2720.     cmpi.b        %d1,&INF        # is operand an INF?
  2721.     bne.b        _L12_4s            # no
  2722.     bsr.l        szr_inf            # yes
  2723.     bra.b        _L12_6s
  2724. _L12_4s:
  2725.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2726.     bne.b        _L12_5s            # no
  2727.     bsr.l        src_qnan            # yes
  2728.     bra.b        _L12_6s
  2729. _L12_5s:
  2730.     bsr.l        stentoxd            # operand is a DENORM
  2731. _L12_6s:
  2732.  
  2733. #
  2734. #    Result is now in FP0
  2735. #
  2736.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2737.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2738.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2739.     unlk        %a6
  2740.     rts
  2741.  
  2742.     global        _ftentoxd_
  2743. _ftentoxd_:
  2744.     link        %a6,&-LOCAL_SIZE
  2745.  
  2746.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2747.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2748.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2749.  
  2750.     fmov.l        &0x0,%fpcr        # zero FPCR
  2751.  
  2752. #
  2753. #    copy, convert, and tag input argument
  2754. #
  2755.     fmov.d        0x8(%a6),%fp0        # load dbl input
  2756.     fmov.x        %fp0,FP_SRC(%a6)
  2757.     lea        FP_SRC(%a6),%a0
  2758.     bsr.l        tag            # fetch operand type
  2759.     mov.b        %d0,STAG(%a6)
  2760.     mov.b        %d0,%d1
  2761.  
  2762.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2763.  
  2764.     clr.l        %d0
  2765.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2766.  
  2767.     mov.b        %d1,STAG(%a6)
  2768.     tst.b        %d1
  2769.     bne.b        _L12_2d
  2770.     bsr.l        stentox            # operand is a NORM
  2771.     bra.b        _L12_6d
  2772. _L12_2d:
  2773.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2774.     bne.b        _L12_3d            # no
  2775.     bsr.l        ld_pone            # yes
  2776.     bra.b        _L12_6d
  2777. _L12_3d:
  2778.     cmpi.b        %d1,&INF        # is operand an INF?
  2779.     bne.b        _L12_4d            # no
  2780.     bsr.l        szr_inf            # yes
  2781.     bra.b        _L12_6d
  2782. _L12_4d:
  2783.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2784.     bne.b        _L12_5d            # no
  2785.     bsr.l        src_qnan            # yes
  2786.     bra.b        _L12_6d
  2787. _L12_5d:
  2788.     bsr.l        stentoxd            # operand is a DENORM
  2789. _L12_6d:
  2790.  
  2791. #
  2792. #    Result is now in FP0
  2793. #
  2794.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2795.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2796.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2797.     unlk        %a6
  2798.     rts
  2799.  
  2800.     global        _ftentoxx_
  2801. _ftentoxx_:
  2802.     link        %a6,&-LOCAL_SIZE
  2803.  
  2804.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2805.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2806.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2807.  
  2808.     fmov.l        &0x0,%fpcr        # zero FPCR
  2809.  
  2810. #
  2811. #    copy, convert, and tag input argument
  2812. #
  2813.     lea        FP_SRC(%a6),%a0
  2814.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  2815.     mov.l        0x8+0x4(%a6),0x4(%a0)
  2816.     mov.l        0x8+0x8(%a6),0x8(%a0)
  2817.     bsr.l        tag            # fetch operand type
  2818.     mov.b        %d0,STAG(%a6)
  2819.     mov.b        %d0,%d1
  2820.  
  2821.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2822.  
  2823.     clr.l        %d0
  2824.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2825.  
  2826.     tst.b        %d1
  2827.     bne.b        _L12_2x
  2828.     bsr.l        stentox            # operand is a NORM
  2829.     bra.b        _L12_6x
  2830. _L12_2x:
  2831.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2832.     bne.b        _L12_3x            # no
  2833.     bsr.l        ld_pone            # yes
  2834.     bra.b        _L12_6x
  2835. _L12_3x:
  2836.     cmpi.b        %d1,&INF        # is operand an INF?
  2837.     bne.b        _L12_4x            # no
  2838.     bsr.l        szr_inf            # yes
  2839.     bra.b        _L12_6x
  2840. _L12_4x:
  2841.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2842.     bne.b        _L12_5x            # no
  2843.     bsr.l        src_qnan            # yes
  2844.     bra.b        _L12_6x
  2845. _L12_5x:
  2846.     bsr.l        stentoxd            # operand is a DENORM
  2847. _L12_6x:
  2848.  
  2849. #
  2850. #    Result is now in FP0
  2851. #
  2852.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2853.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2854.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2855.     unlk        %a6
  2856.     rts
  2857.  
  2858.  
  2859. #########################################################################
  2860. # MONADIC TEMPLATE                            #
  2861. #########################################################################
  2862.     global        _flogns_
  2863. _flogns_:
  2864.     link        %a6,&-LOCAL_SIZE
  2865.  
  2866.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2867.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2868.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2869.  
  2870.     fmov.l        &0x0,%fpcr        # zero FPCR
  2871.  
  2872. #
  2873. #    copy, convert, and tag input argument
  2874. #
  2875.     fmov.s        0x8(%a6),%fp0        # load sgl input
  2876.     fmov.x        %fp0,FP_SRC(%a6)
  2877.     lea        FP_SRC(%a6),%a0
  2878.     bsr.l        tag            # fetch operand type
  2879.     mov.b        %d0,STAG(%a6)
  2880.     mov.b        %d0,%d1
  2881.  
  2882.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2883.  
  2884.     clr.l        %d0
  2885.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2886.  
  2887.     tst.b        %d1
  2888.     bne.b        _L13_2s
  2889.     bsr.l        slogn            # operand is a NORM
  2890.     bra.b        _L13_6s
  2891. _L13_2s:
  2892.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2893.     bne.b        _L13_3s            # no
  2894.     bsr.l        t_dz2            # yes
  2895.     bra.b        _L13_6s
  2896. _L13_3s:
  2897.     cmpi.b        %d1,&INF        # is operand an INF?
  2898.     bne.b        _L13_4s            # no
  2899.     bsr.l        sopr_inf            # yes
  2900.     bra.b        _L13_6s
  2901. _L13_4s:
  2902.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2903.     bne.b        _L13_5s            # no
  2904.     bsr.l        src_qnan            # yes
  2905.     bra.b        _L13_6s
  2906. _L13_5s:
  2907.     bsr.l        slognd            # operand is a DENORM
  2908. _L13_6s:
  2909.  
  2910. #
  2911. #    Result is now in FP0
  2912. #
  2913.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2914.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2915.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2916.     unlk        %a6
  2917.     rts
  2918.  
  2919.     global        _flognd_
  2920. _flognd_:
  2921.     link        %a6,&-LOCAL_SIZE
  2922.  
  2923.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2924.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2925.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2926.  
  2927.     fmov.l        &0x0,%fpcr        # zero FPCR
  2928.  
  2929. #
  2930. #    copy, convert, and tag input argument
  2931. #
  2932.     fmov.d        0x8(%a6),%fp0        # load dbl input
  2933.     fmov.x        %fp0,FP_SRC(%a6)
  2934.     lea        FP_SRC(%a6),%a0
  2935.     bsr.l        tag            # fetch operand type
  2936.     mov.b        %d0,STAG(%a6)
  2937.     mov.b        %d0,%d1
  2938.  
  2939.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2940.  
  2941.     clr.l        %d0
  2942.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  2943.  
  2944.     mov.b        %d1,STAG(%a6)
  2945.     tst.b        %d1
  2946.     bne.b        _L13_2d
  2947.     bsr.l        slogn            # operand is a NORM
  2948.     bra.b        _L13_6d
  2949. _L13_2d:
  2950.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  2951.     bne.b        _L13_3d            # no
  2952.     bsr.l        t_dz2            # yes
  2953.     bra.b        _L13_6d
  2954. _L13_3d:
  2955.     cmpi.b        %d1,&INF        # is operand an INF?
  2956.     bne.b        _L13_4d            # no
  2957.     bsr.l        sopr_inf            # yes
  2958.     bra.b        _L13_6d
  2959. _L13_4d:
  2960.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  2961.     bne.b        _L13_5d            # no
  2962.     bsr.l        src_qnan            # yes
  2963.     bra.b        _L13_6d
  2964. _L13_5d:
  2965.     bsr.l        slognd            # operand is a DENORM
  2966. _L13_6d:
  2967.  
  2968. #
  2969. #    Result is now in FP0
  2970. #
  2971.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  2972.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  2973.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  2974.     unlk        %a6
  2975.     rts
  2976.  
  2977.     global        _flognx_
  2978. _flognx_:
  2979.     link        %a6,&-LOCAL_SIZE
  2980.  
  2981.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  2982.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  2983.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  2984.  
  2985.     fmov.l        &0x0,%fpcr        # zero FPCR
  2986.  
  2987. #
  2988. #    copy, convert, and tag input argument
  2989. #
  2990.     lea        FP_SRC(%a6),%a0
  2991.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  2992.     mov.l        0x8+0x4(%a6),0x4(%a0)
  2993.     mov.l        0x8+0x8(%a6),0x8(%a0)
  2994.     bsr.l        tag            # fetch operand type
  2995.     mov.b        %d0,STAG(%a6)
  2996.     mov.b        %d0,%d1
  2997.  
  2998.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  2999.  
  3000.     clr.l        %d0
  3001.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3002.  
  3003.     tst.b        %d1
  3004.     bne.b        _L13_2x
  3005.     bsr.l        slogn            # operand is a NORM
  3006.     bra.b        _L13_6x
  3007. _L13_2x:
  3008.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3009.     bne.b        _L13_3x            # no
  3010.     bsr.l        t_dz2            # yes
  3011.     bra.b        _L13_6x
  3012. _L13_3x:
  3013.     cmpi.b        %d1,&INF        # is operand an INF?
  3014.     bne.b        _L13_4x            # no
  3015.     bsr.l        sopr_inf            # yes
  3016.     bra.b        _L13_6x
  3017. _L13_4x:
  3018.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3019.     bne.b        _L13_5x            # no
  3020.     bsr.l        src_qnan            # yes
  3021.     bra.b        _L13_6x
  3022. _L13_5x:
  3023.     bsr.l        slognd            # operand is a DENORM
  3024. _L13_6x:
  3025.  
  3026. #
  3027. #    Result is now in FP0
  3028. #
  3029.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3030.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3031.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3032.     unlk        %a6
  3033.     rts
  3034.  
  3035.  
  3036. #########################################################################
  3037. # MONADIC TEMPLATE                            #
  3038. #########################################################################
  3039.     global        _flog10s_
  3040. _flog10s_:
  3041.     link        %a6,&-LOCAL_SIZE
  3042.  
  3043.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3044.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3045.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3046.  
  3047.     fmov.l        &0x0,%fpcr        # zero FPCR
  3048.  
  3049. #
  3050. #    copy, convert, and tag input argument
  3051. #
  3052.     fmov.s        0x8(%a6),%fp0        # load sgl input
  3053.     fmov.x        %fp0,FP_SRC(%a6)
  3054.     lea        FP_SRC(%a6),%a0
  3055.     bsr.l        tag            # fetch operand type
  3056.     mov.b        %d0,STAG(%a6)
  3057.     mov.b        %d0,%d1
  3058.  
  3059.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3060.  
  3061.     clr.l        %d0
  3062.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3063.  
  3064.     tst.b        %d1
  3065.     bne.b        _L14_2s
  3066.     bsr.l        slog10            # operand is a NORM
  3067.     bra.b        _L14_6s
  3068. _L14_2s:
  3069.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3070.     bne.b        _L14_3s            # no
  3071.     bsr.l        t_dz2            # yes
  3072.     bra.b        _L14_6s
  3073. _L14_3s:
  3074.     cmpi.b        %d1,&INF        # is operand an INF?
  3075.     bne.b        _L14_4s            # no
  3076.     bsr.l        sopr_inf            # yes
  3077.     bra.b        _L14_6s
  3078. _L14_4s:
  3079.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3080.     bne.b        _L14_5s            # no
  3081.     bsr.l        src_qnan            # yes
  3082.     bra.b        _L14_6s
  3083. _L14_5s:
  3084.     bsr.l        slog10d            # operand is a DENORM
  3085. _L14_6s:
  3086.  
  3087. #
  3088. #    Result is now in FP0
  3089. #
  3090.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3091.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3092.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3093.     unlk        %a6
  3094.     rts
  3095.  
  3096.     global        _flog10d_
  3097. _flog10d_:
  3098.     link        %a6,&-LOCAL_SIZE
  3099.  
  3100.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3101.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3102.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3103.  
  3104.     fmov.l        &0x0,%fpcr        # zero FPCR
  3105.  
  3106. #
  3107. #    copy, convert, and tag input argument
  3108. #
  3109.     fmov.d        0x8(%a6),%fp0        # load dbl input
  3110.     fmov.x        %fp0,FP_SRC(%a6)
  3111.     lea        FP_SRC(%a6),%a0
  3112.     bsr.l        tag            # fetch operand type
  3113.     mov.b        %d0,STAG(%a6)
  3114.     mov.b        %d0,%d1
  3115.  
  3116.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3117.  
  3118.     clr.l        %d0
  3119.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3120.  
  3121.     mov.b        %d1,STAG(%a6)
  3122.     tst.b        %d1
  3123.     bne.b        _L14_2d
  3124.     bsr.l        slog10            # operand is a NORM
  3125.     bra.b        _L14_6d
  3126. _L14_2d:
  3127.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3128.     bne.b        _L14_3d            # no
  3129.     bsr.l        t_dz2            # yes
  3130.     bra.b        _L14_6d
  3131. _L14_3d:
  3132.     cmpi.b        %d1,&INF        # is operand an INF?
  3133.     bne.b        _L14_4d            # no
  3134.     bsr.l        sopr_inf            # yes
  3135.     bra.b        _L14_6d
  3136. _L14_4d:
  3137.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3138.     bne.b        _L14_5d            # no
  3139.     bsr.l        src_qnan            # yes
  3140.     bra.b        _L14_6d
  3141. _L14_5d:
  3142.     bsr.l        slog10d            # operand is a DENORM
  3143. _L14_6d:
  3144.  
  3145. #
  3146. #    Result is now in FP0
  3147. #
  3148.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3149.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3150.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3151.     unlk        %a6
  3152.     rts
  3153.  
  3154.     global        _flog10x_
  3155. _flog10x_:
  3156.     link        %a6,&-LOCAL_SIZE
  3157.  
  3158.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3159.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3160.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3161.  
  3162.     fmov.l        &0x0,%fpcr        # zero FPCR
  3163.  
  3164. #
  3165. #    copy, convert, and tag input argument
  3166. #
  3167.     lea        FP_SRC(%a6),%a0
  3168.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  3169.     mov.l        0x8+0x4(%a6),0x4(%a0)
  3170.     mov.l        0x8+0x8(%a6),0x8(%a0)
  3171.     bsr.l        tag            # fetch operand type
  3172.     mov.b        %d0,STAG(%a6)
  3173.     mov.b        %d0,%d1
  3174.  
  3175.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3176.  
  3177.     clr.l        %d0
  3178.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3179.  
  3180.     tst.b        %d1
  3181.     bne.b        _L14_2x
  3182.     bsr.l        slog10            # operand is a NORM
  3183.     bra.b        _L14_6x
  3184. _L14_2x:
  3185.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3186.     bne.b        _L14_3x            # no
  3187.     bsr.l        t_dz2            # yes
  3188.     bra.b        _L14_6x
  3189. _L14_3x:
  3190.     cmpi.b        %d1,&INF        # is operand an INF?
  3191.     bne.b        _L14_4x            # no
  3192.     bsr.l        sopr_inf            # yes
  3193.     bra.b        _L14_6x
  3194. _L14_4x:
  3195.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3196.     bne.b        _L14_5x            # no
  3197.     bsr.l        src_qnan            # yes
  3198.     bra.b        _L14_6x
  3199. _L14_5x:
  3200.     bsr.l        slog10d            # operand is a DENORM
  3201. _L14_6x:
  3202.  
  3203. #
  3204. #    Result is now in FP0
  3205. #
  3206.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3207.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3208.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3209.     unlk        %a6
  3210.     rts
  3211.  
  3212.  
  3213. #########################################################################
  3214. # MONADIC TEMPLATE                            #
  3215. #########################################################################
  3216.     global        _flog2s_
  3217. _flog2s_:
  3218.     link        %a6,&-LOCAL_SIZE
  3219.  
  3220.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3221.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3222.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3223.  
  3224.     fmov.l        &0x0,%fpcr        # zero FPCR
  3225.  
  3226. #
  3227. #    copy, convert, and tag input argument
  3228. #
  3229.     fmov.s        0x8(%a6),%fp0        # load sgl input
  3230.     fmov.x        %fp0,FP_SRC(%a6)
  3231.     lea        FP_SRC(%a6),%a0
  3232.     bsr.l        tag            # fetch operand type
  3233.     mov.b        %d0,STAG(%a6)
  3234.     mov.b        %d0,%d1
  3235.  
  3236.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3237.  
  3238.     clr.l        %d0
  3239.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3240.  
  3241.     tst.b        %d1
  3242.     bne.b        _L15_2s
  3243.     bsr.l        slog2            # operand is a NORM
  3244.     bra.b        _L15_6s
  3245. _L15_2s:
  3246.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3247.     bne.b        _L15_3s            # no
  3248.     bsr.l        t_dz2            # yes
  3249.     bra.b        _L15_6s
  3250. _L15_3s:
  3251.     cmpi.b        %d1,&INF        # is operand an INF?
  3252.     bne.b        _L15_4s            # no
  3253.     bsr.l        sopr_inf            # yes
  3254.     bra.b        _L15_6s
  3255. _L15_4s:
  3256.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3257.     bne.b        _L15_5s            # no
  3258.     bsr.l        src_qnan            # yes
  3259.     bra.b        _L15_6s
  3260. _L15_5s:
  3261.     bsr.l        slog2d            # operand is a DENORM
  3262. _L15_6s:
  3263.  
  3264. #
  3265. #    Result is now in FP0
  3266. #
  3267.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3268.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3269.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3270.     unlk        %a6
  3271.     rts
  3272.  
  3273.     global        _flog2d_
  3274. _flog2d_:
  3275.     link        %a6,&-LOCAL_SIZE
  3276.  
  3277.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3278.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3279.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3280.  
  3281.     fmov.l        &0x0,%fpcr        # zero FPCR
  3282.  
  3283. #
  3284. #    copy, convert, and tag input argument
  3285. #
  3286.     fmov.d        0x8(%a6),%fp0        # load dbl input
  3287.     fmov.x        %fp0,FP_SRC(%a6)
  3288.     lea        FP_SRC(%a6),%a0
  3289.     bsr.l        tag            # fetch operand type
  3290.     mov.b        %d0,STAG(%a6)
  3291.     mov.b        %d0,%d1
  3292.  
  3293.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3294.  
  3295.     clr.l        %d0
  3296.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3297.  
  3298.     mov.b        %d1,STAG(%a6)
  3299.     tst.b        %d1
  3300.     bne.b        _L15_2d
  3301.     bsr.l        slog2            # operand is a NORM
  3302.     bra.b        _L15_6d
  3303. _L15_2d:
  3304.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3305.     bne.b        _L15_3d            # no
  3306.     bsr.l        t_dz2            # yes
  3307.     bra.b        _L15_6d
  3308. _L15_3d:
  3309.     cmpi.b        %d1,&INF        # is operand an INF?
  3310.     bne.b        _L15_4d            # no
  3311.     bsr.l        sopr_inf            # yes
  3312.     bra.b        _L15_6d
  3313. _L15_4d:
  3314.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3315.     bne.b        _L15_5d            # no
  3316.     bsr.l        src_qnan            # yes
  3317.     bra.b        _L15_6d
  3318. _L15_5d:
  3319.     bsr.l        slog2d            # operand is a DENORM
  3320. _L15_6d:
  3321.  
  3322. #
  3323. #    Result is now in FP0
  3324. #
  3325.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3326.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3327.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3328.     unlk        %a6
  3329.     rts
  3330.  
  3331.     global        _flog2x_
  3332. _flog2x_:
  3333.     link        %a6,&-LOCAL_SIZE
  3334.  
  3335.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3336.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3337.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3338.  
  3339.     fmov.l        &0x0,%fpcr        # zero FPCR
  3340.  
  3341. #
  3342. #    copy, convert, and tag input argument
  3343. #
  3344.     lea        FP_SRC(%a6),%a0
  3345.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  3346.     mov.l        0x8+0x4(%a6),0x4(%a0)
  3347.     mov.l        0x8+0x8(%a6),0x8(%a0)
  3348.     bsr.l        tag            # fetch operand type
  3349.     mov.b        %d0,STAG(%a6)
  3350.     mov.b        %d0,%d1
  3351.  
  3352.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3353.  
  3354.     clr.l        %d0
  3355.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3356.  
  3357.     tst.b        %d1
  3358.     bne.b        _L15_2x
  3359.     bsr.l        slog2            # operand is a NORM
  3360.     bra.b        _L15_6x
  3361. _L15_2x:
  3362.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3363.     bne.b        _L15_3x            # no
  3364.     bsr.l        t_dz2            # yes
  3365.     bra.b        _L15_6x
  3366. _L15_3x:
  3367.     cmpi.b        %d1,&INF        # is operand an INF?
  3368.     bne.b        _L15_4x            # no
  3369.     bsr.l        sopr_inf            # yes
  3370.     bra.b        _L15_6x
  3371. _L15_4x:
  3372.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3373.     bne.b        _L15_5x            # no
  3374.     bsr.l        src_qnan            # yes
  3375.     bra.b        _L15_6x
  3376. _L15_5x:
  3377.     bsr.l        slog2d            # operand is a DENORM
  3378. _L15_6x:
  3379.  
  3380. #
  3381. #    Result is now in FP0
  3382. #
  3383.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3384.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3385.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3386.     unlk        %a6
  3387.     rts
  3388.  
  3389.  
  3390. #########################################################################
  3391. # MONADIC TEMPLATE                            #
  3392. #########################################################################
  3393.     global        _fcoshs_
  3394. _fcoshs_:
  3395.     link        %a6,&-LOCAL_SIZE
  3396.  
  3397.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3398.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3399.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3400.  
  3401.     fmov.l        &0x0,%fpcr        # zero FPCR
  3402.  
  3403. #
  3404. #    copy, convert, and tag input argument
  3405. #
  3406.     fmov.s        0x8(%a6),%fp0        # load sgl input
  3407.     fmov.x        %fp0,FP_SRC(%a6)
  3408.     lea        FP_SRC(%a6),%a0
  3409.     bsr.l        tag            # fetch operand type
  3410.     mov.b        %d0,STAG(%a6)
  3411.     mov.b        %d0,%d1
  3412.  
  3413.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3414.  
  3415.     clr.l        %d0
  3416.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3417.  
  3418.     tst.b        %d1
  3419.     bne.b        _L16_2s
  3420.     bsr.l        scosh            # operand is a NORM
  3421.     bra.b        _L16_6s
  3422. _L16_2s:
  3423.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3424.     bne.b        _L16_3s            # no
  3425.     bsr.l        ld_pone            # yes
  3426.     bra.b        _L16_6s
  3427. _L16_3s:
  3428.     cmpi.b        %d1,&INF        # is operand an INF?
  3429.     bne.b        _L16_4s            # no
  3430.     bsr.l        ld_pinf            # yes
  3431.     bra.b        _L16_6s
  3432. _L16_4s:
  3433.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3434.     bne.b        _L16_5s            # no
  3435.     bsr.l        src_qnan            # yes
  3436.     bra.b        _L16_6s
  3437. _L16_5s:
  3438.     bsr.l        scoshd            # operand is a DENORM
  3439. _L16_6s:
  3440.  
  3441. #
  3442. #    Result is now in FP0
  3443. #
  3444.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3445.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3446.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3447.     unlk        %a6
  3448.     rts
  3449.  
  3450.     global        _fcoshd_
  3451. _fcoshd_:
  3452.     link        %a6,&-LOCAL_SIZE
  3453.  
  3454.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3455.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3456.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3457.  
  3458.     fmov.l        &0x0,%fpcr        # zero FPCR
  3459.  
  3460. #
  3461. #    copy, convert, and tag input argument
  3462. #
  3463.     fmov.d        0x8(%a6),%fp0        # load dbl input
  3464.     fmov.x        %fp0,FP_SRC(%a6)
  3465.     lea        FP_SRC(%a6),%a0
  3466.     bsr.l        tag            # fetch operand type
  3467.     mov.b        %d0,STAG(%a6)
  3468.     mov.b        %d0,%d1
  3469.  
  3470.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3471.  
  3472.     clr.l        %d0
  3473.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3474.  
  3475.     mov.b        %d1,STAG(%a6)
  3476.     tst.b        %d1
  3477.     bne.b        _L16_2d
  3478.     bsr.l        scosh            # operand is a NORM
  3479.     bra.b        _L16_6d
  3480. _L16_2d:
  3481.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3482.     bne.b        _L16_3d            # no
  3483.     bsr.l        ld_pone            # yes
  3484.     bra.b        _L16_6d
  3485. _L16_3d:
  3486.     cmpi.b        %d1,&INF        # is operand an INF?
  3487.     bne.b        _L16_4d            # no
  3488.     bsr.l        ld_pinf            # yes
  3489.     bra.b        _L16_6d
  3490. _L16_4d:
  3491.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3492.     bne.b        _L16_5d            # no
  3493.     bsr.l        src_qnan            # yes
  3494.     bra.b        _L16_6d
  3495. _L16_5d:
  3496.     bsr.l        scoshd            # operand is a DENORM
  3497. _L16_6d:
  3498.  
  3499. #
  3500. #    Result is now in FP0
  3501. #
  3502.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3503.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3504.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3505.     unlk        %a6
  3506.     rts
  3507.  
  3508.     global        _fcoshx_
  3509. _fcoshx_:
  3510.     link        %a6,&-LOCAL_SIZE
  3511.  
  3512.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3513.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3514.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3515.  
  3516.     fmov.l        &0x0,%fpcr        # zero FPCR
  3517.  
  3518. #
  3519. #    copy, convert, and tag input argument
  3520. #
  3521.     lea        FP_SRC(%a6),%a0
  3522.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  3523.     mov.l        0x8+0x4(%a6),0x4(%a0)
  3524.     mov.l        0x8+0x8(%a6),0x8(%a0)
  3525.     bsr.l        tag            # fetch operand type
  3526.     mov.b        %d0,STAG(%a6)
  3527.     mov.b        %d0,%d1
  3528.  
  3529.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3530.  
  3531.     clr.l        %d0
  3532.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3533.  
  3534.     tst.b        %d1
  3535.     bne.b        _L16_2x
  3536.     bsr.l        scosh            # operand is a NORM
  3537.     bra.b        _L16_6x
  3538. _L16_2x:
  3539.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3540.     bne.b        _L16_3x            # no
  3541.     bsr.l        ld_pone            # yes
  3542.     bra.b        _L16_6x
  3543. _L16_3x:
  3544.     cmpi.b        %d1,&INF        # is operand an INF?
  3545.     bne.b        _L16_4x            # no
  3546.     bsr.l        ld_pinf            # yes
  3547.     bra.b        _L16_6x
  3548. _L16_4x:
  3549.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3550.     bne.b        _L16_5x            # no
  3551.     bsr.l        src_qnan            # yes
  3552.     bra.b        _L16_6x
  3553. _L16_5x:
  3554.     bsr.l        scoshd            # operand is a DENORM
  3555. _L16_6x:
  3556.  
  3557. #
  3558. #    Result is now in FP0
  3559. #
  3560.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3561.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3562.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3563.     unlk        %a6
  3564.     rts
  3565.  
  3566.  
  3567. #########################################################################
  3568. # MONADIC TEMPLATE                            #
  3569. #########################################################################
  3570.     global        _facoss_
  3571. _facoss_:
  3572.     link        %a6,&-LOCAL_SIZE
  3573.  
  3574.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3575.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3576.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3577.  
  3578.     fmov.l        &0x0,%fpcr        # zero FPCR
  3579.  
  3580. #
  3581. #    copy, convert, and tag input argument
  3582. #
  3583.     fmov.s        0x8(%a6),%fp0        # load sgl input
  3584.     fmov.x        %fp0,FP_SRC(%a6)
  3585.     lea        FP_SRC(%a6),%a0
  3586.     bsr.l        tag            # fetch operand type
  3587.     mov.b        %d0,STAG(%a6)
  3588.     mov.b        %d0,%d1
  3589.  
  3590.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3591.  
  3592.     clr.l        %d0
  3593.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3594.  
  3595.     tst.b        %d1
  3596.     bne.b        _L17_2s
  3597.     bsr.l        sacos            # operand is a NORM
  3598.     bra.b        _L17_6s
  3599. _L17_2s:
  3600.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3601.     bne.b        _L17_3s            # no
  3602.     bsr.l        ld_ppi2            # yes
  3603.     bra.b        _L17_6s
  3604. _L17_3s:
  3605.     cmpi.b        %d1,&INF        # is operand an INF?
  3606.     bne.b        _L17_4s            # no
  3607.     bsr.l        t_operr            # yes
  3608.     bra.b        _L17_6s
  3609. _L17_4s:
  3610.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3611.     bne.b        _L17_5s            # no
  3612.     bsr.l        src_qnan            # yes
  3613.     bra.b        _L17_6s
  3614. _L17_5s:
  3615.     bsr.l        sacosd            # operand is a DENORM
  3616. _L17_6s:
  3617.  
  3618. #
  3619. #    Result is now in FP0
  3620. #
  3621.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3622.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3623.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3624.     unlk        %a6
  3625.     rts
  3626.  
  3627.     global        _facosd_
  3628. _facosd_:
  3629.     link        %a6,&-LOCAL_SIZE
  3630.  
  3631.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3632.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3633.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3634.  
  3635.     fmov.l        &0x0,%fpcr        # zero FPCR
  3636.  
  3637. #
  3638. #    copy, convert, and tag input argument
  3639. #
  3640.     fmov.d        0x8(%a6),%fp0        # load dbl input
  3641.     fmov.x        %fp0,FP_SRC(%a6)
  3642.     lea        FP_SRC(%a6),%a0
  3643.     bsr.l        tag            # fetch operand type
  3644.     mov.b        %d0,STAG(%a6)
  3645.     mov.b        %d0,%d1
  3646.  
  3647.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3648.  
  3649.     clr.l        %d0
  3650.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3651.  
  3652.     mov.b        %d1,STAG(%a6)
  3653.     tst.b        %d1
  3654.     bne.b        _L17_2d
  3655.     bsr.l        sacos            # operand is a NORM
  3656.     bra.b        _L17_6d
  3657. _L17_2d:
  3658.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3659.     bne.b        _L17_3d            # no
  3660.     bsr.l        ld_ppi2            # yes
  3661.     bra.b        _L17_6d
  3662. _L17_3d:
  3663.     cmpi.b        %d1,&INF        # is operand an INF?
  3664.     bne.b        _L17_4d            # no
  3665.     bsr.l        t_operr            # yes
  3666.     bra.b        _L17_6d
  3667. _L17_4d:
  3668.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3669.     bne.b        _L17_5d            # no
  3670.     bsr.l        src_qnan            # yes
  3671.     bra.b        _L17_6d
  3672. _L17_5d:
  3673.     bsr.l        sacosd            # operand is a DENORM
  3674. _L17_6d:
  3675.  
  3676. #
  3677. #    Result is now in FP0
  3678. #
  3679.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3680.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3681.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3682.     unlk        %a6
  3683.     rts
  3684.  
  3685.     global        _facosx_
  3686. _facosx_:
  3687.     link        %a6,&-LOCAL_SIZE
  3688.  
  3689.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3690.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3691.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3692.  
  3693.     fmov.l        &0x0,%fpcr        # zero FPCR
  3694.  
  3695. #
  3696. #    copy, convert, and tag input argument
  3697. #
  3698.     lea        FP_SRC(%a6),%a0
  3699.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  3700.     mov.l        0x8+0x4(%a6),0x4(%a0)
  3701.     mov.l        0x8+0x8(%a6),0x8(%a0)
  3702.     bsr.l        tag            # fetch operand type
  3703.     mov.b        %d0,STAG(%a6)
  3704.     mov.b        %d0,%d1
  3705.  
  3706.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3707.  
  3708.     clr.l        %d0
  3709.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3710.  
  3711.     tst.b        %d1
  3712.     bne.b        _L17_2x
  3713.     bsr.l        sacos            # operand is a NORM
  3714.     bra.b        _L17_6x
  3715. _L17_2x:
  3716.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3717.     bne.b        _L17_3x            # no
  3718.     bsr.l        ld_ppi2            # yes
  3719.     bra.b        _L17_6x
  3720. _L17_3x:
  3721.     cmpi.b        %d1,&INF        # is operand an INF?
  3722.     bne.b        _L17_4x            # no
  3723.     bsr.l        t_operr            # yes
  3724.     bra.b        _L17_6x
  3725. _L17_4x:
  3726.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3727.     bne.b        _L17_5x            # no
  3728.     bsr.l        src_qnan            # yes
  3729.     bra.b        _L17_6x
  3730. _L17_5x:
  3731.     bsr.l        sacosd            # operand is a DENORM
  3732. _L17_6x:
  3733.  
  3734. #
  3735. #    Result is now in FP0
  3736. #
  3737.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3738.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3739.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3740.     unlk        %a6
  3741.     rts
  3742.  
  3743.  
  3744. #########################################################################
  3745. # MONADIC TEMPLATE                            #
  3746. #########################################################################
  3747.     global        _fgetexps_
  3748. _fgetexps_:
  3749.     link        %a6,&-LOCAL_SIZE
  3750.  
  3751.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3752.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3753.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3754.  
  3755.     fmov.l        &0x0,%fpcr        # zero FPCR
  3756.  
  3757. #
  3758. #    copy, convert, and tag input argument
  3759. #
  3760.     fmov.s        0x8(%a6),%fp0        # load sgl input
  3761.     fmov.x        %fp0,FP_SRC(%a6)
  3762.     lea        FP_SRC(%a6),%a0
  3763.     bsr.l        tag            # fetch operand type
  3764.     mov.b        %d0,STAG(%a6)
  3765.     mov.b        %d0,%d1
  3766.  
  3767.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3768.  
  3769.     clr.l        %d0
  3770.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3771.  
  3772.     tst.b        %d1
  3773.     bne.b        _L18_2s
  3774.     bsr.l        sgetexp            # operand is a NORM
  3775.     bra.b        _L18_6s
  3776. _L18_2s:
  3777.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3778.     bne.b        _L18_3s            # no
  3779.     bsr.l        src_zero            # yes
  3780.     bra.b        _L18_6s
  3781. _L18_3s:
  3782.     cmpi.b        %d1,&INF        # is operand an INF?
  3783.     bne.b        _L18_4s            # no
  3784.     bsr.l        t_operr            # yes
  3785.     bra.b        _L18_6s
  3786. _L18_4s:
  3787.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3788.     bne.b        _L18_5s            # no
  3789.     bsr.l        src_qnan            # yes
  3790.     bra.b        _L18_6s
  3791. _L18_5s:
  3792.     bsr.l        sgetexpd            # operand is a DENORM
  3793. _L18_6s:
  3794.  
  3795. #
  3796. #    Result is now in FP0
  3797. #
  3798.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3799.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3800.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3801.     unlk        %a6
  3802.     rts
  3803.  
  3804.     global        _fgetexpd_
  3805. _fgetexpd_:
  3806.     link        %a6,&-LOCAL_SIZE
  3807.  
  3808.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3809.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3810.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3811.  
  3812.     fmov.l        &0x0,%fpcr        # zero FPCR
  3813.  
  3814. #
  3815. #    copy, convert, and tag input argument
  3816. #
  3817.     fmov.d        0x8(%a6),%fp0        # load dbl input
  3818.     fmov.x        %fp0,FP_SRC(%a6)
  3819.     lea        FP_SRC(%a6),%a0
  3820.     bsr.l        tag            # fetch operand type
  3821.     mov.b        %d0,STAG(%a6)
  3822.     mov.b        %d0,%d1
  3823.  
  3824.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3825.  
  3826.     clr.l        %d0
  3827.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3828.  
  3829.     mov.b        %d1,STAG(%a6)
  3830.     tst.b        %d1
  3831.     bne.b        _L18_2d
  3832.     bsr.l        sgetexp            # operand is a NORM
  3833.     bra.b        _L18_6d
  3834. _L18_2d:
  3835.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3836.     bne.b        _L18_3d            # no
  3837.     bsr.l        src_zero            # yes
  3838.     bra.b        _L18_6d
  3839. _L18_3d:
  3840.     cmpi.b        %d1,&INF        # is operand an INF?
  3841.     bne.b        _L18_4d            # no
  3842.     bsr.l        t_operr            # yes
  3843.     bra.b        _L18_6d
  3844. _L18_4d:
  3845.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3846.     bne.b        _L18_5d            # no
  3847.     bsr.l        src_qnan            # yes
  3848.     bra.b        _L18_6d
  3849. _L18_5d:
  3850.     bsr.l        sgetexpd            # operand is a DENORM
  3851. _L18_6d:
  3852.  
  3853. #
  3854. #    Result is now in FP0
  3855. #
  3856.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3857.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3858.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3859.     unlk        %a6
  3860.     rts
  3861.  
  3862.     global        _fgetexpx_
  3863. _fgetexpx_:
  3864.     link        %a6,&-LOCAL_SIZE
  3865.  
  3866.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3867.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3868.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3869.  
  3870.     fmov.l        &0x0,%fpcr        # zero FPCR
  3871.  
  3872. #
  3873. #    copy, convert, and tag input argument
  3874. #
  3875.     lea        FP_SRC(%a6),%a0
  3876.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  3877.     mov.l        0x8+0x4(%a6),0x4(%a0)
  3878.     mov.l        0x8+0x8(%a6),0x8(%a0)
  3879.     bsr.l        tag            # fetch operand type
  3880.     mov.b        %d0,STAG(%a6)
  3881.     mov.b        %d0,%d1
  3882.  
  3883.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3884.  
  3885.     clr.l        %d0
  3886.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3887.  
  3888.     tst.b        %d1
  3889.     bne.b        _L18_2x
  3890.     bsr.l        sgetexp            # operand is a NORM
  3891.     bra.b        _L18_6x
  3892. _L18_2x:
  3893.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3894.     bne.b        _L18_3x            # no
  3895.     bsr.l        src_zero            # yes
  3896.     bra.b        _L18_6x
  3897. _L18_3x:
  3898.     cmpi.b        %d1,&INF        # is operand an INF?
  3899.     bne.b        _L18_4x            # no
  3900.     bsr.l        t_operr            # yes
  3901.     bra.b        _L18_6x
  3902. _L18_4x:
  3903.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3904.     bne.b        _L18_5x            # no
  3905.     bsr.l        src_qnan            # yes
  3906.     bra.b        _L18_6x
  3907. _L18_5x:
  3908.     bsr.l        sgetexpd            # operand is a DENORM
  3909. _L18_6x:
  3910.  
  3911. #
  3912. #    Result is now in FP0
  3913. #
  3914.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3915.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3916.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3917.     unlk        %a6
  3918.     rts
  3919.  
  3920.  
  3921. #########################################################################
  3922. # MONADIC TEMPLATE                            #
  3923. #########################################################################
  3924.     global        _fgetmans_
  3925. _fgetmans_:
  3926.     link        %a6,&-LOCAL_SIZE
  3927.  
  3928.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3929.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3930.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3931.  
  3932.     fmov.l        &0x0,%fpcr        # zero FPCR
  3933.  
  3934. #
  3935. #    copy, convert, and tag input argument
  3936. #
  3937.     fmov.s        0x8(%a6),%fp0        # load sgl input
  3938.     fmov.x        %fp0,FP_SRC(%a6)
  3939.     lea        FP_SRC(%a6),%a0
  3940.     bsr.l        tag            # fetch operand type
  3941.     mov.b        %d0,STAG(%a6)
  3942.     mov.b        %d0,%d1
  3943.  
  3944.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  3945.  
  3946.     clr.l        %d0
  3947.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  3948.  
  3949.     tst.b        %d1
  3950.     bne.b        _L19_2s
  3951.     bsr.l        sgetman            # operand is a NORM
  3952.     bra.b        _L19_6s
  3953. _L19_2s:
  3954.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  3955.     bne.b        _L19_3s            # no
  3956.     bsr.l        src_zero            # yes
  3957.     bra.b        _L19_6s
  3958. _L19_3s:
  3959.     cmpi.b        %d1,&INF        # is operand an INF?
  3960.     bne.b        _L19_4s            # no
  3961.     bsr.l        t_operr            # yes
  3962.     bra.b        _L19_6s
  3963. _L19_4s:
  3964.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  3965.     bne.b        _L19_5s            # no
  3966.     bsr.l        src_qnan            # yes
  3967.     bra.b        _L19_6s
  3968. _L19_5s:
  3969.     bsr.l        sgetmand            # operand is a DENORM
  3970. _L19_6s:
  3971.  
  3972. #
  3973. #    Result is now in FP0
  3974. #
  3975.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  3976.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  3977.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  3978.     unlk        %a6
  3979.     rts
  3980.  
  3981.     global        _fgetmand_
  3982. _fgetmand_:
  3983.     link        %a6,&-LOCAL_SIZE
  3984.  
  3985.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  3986.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  3987.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  3988.  
  3989.     fmov.l        &0x0,%fpcr        # zero FPCR
  3990.  
  3991. #
  3992. #    copy, convert, and tag input argument
  3993. #
  3994.     fmov.d        0x8(%a6),%fp0        # load dbl input
  3995.     fmov.x        %fp0,FP_SRC(%a6)
  3996.     lea        FP_SRC(%a6),%a0
  3997.     bsr.l        tag            # fetch operand type
  3998.     mov.b        %d0,STAG(%a6)
  3999.     mov.b        %d0,%d1
  4000.  
  4001.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4002.  
  4003.     clr.l        %d0
  4004.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4005.  
  4006.     mov.b        %d1,STAG(%a6)
  4007.     tst.b        %d1
  4008.     bne.b        _L19_2d
  4009.     bsr.l        sgetman            # operand is a NORM
  4010.     bra.b        _L19_6d
  4011. _L19_2d:
  4012.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4013.     bne.b        _L19_3d            # no
  4014.     bsr.l        src_zero            # yes
  4015.     bra.b        _L19_6d
  4016. _L19_3d:
  4017.     cmpi.b        %d1,&INF        # is operand an INF?
  4018.     bne.b        _L19_4d            # no
  4019.     bsr.l        t_operr            # yes
  4020.     bra.b        _L19_6d
  4021. _L19_4d:
  4022.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4023.     bne.b        _L19_5d            # no
  4024.     bsr.l        src_qnan            # yes
  4025.     bra.b        _L19_6d
  4026. _L19_5d:
  4027.     bsr.l        sgetmand            # operand is a DENORM
  4028. _L19_6d:
  4029.  
  4030. #
  4031. #    Result is now in FP0
  4032. #
  4033.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4034.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4035.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  4036.     unlk        %a6
  4037.     rts
  4038.  
  4039.     global        _fgetmanx_
  4040. _fgetmanx_:
  4041.     link        %a6,&-LOCAL_SIZE
  4042.  
  4043.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  4044.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4045.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  4046.  
  4047.     fmov.l        &0x0,%fpcr        # zero FPCR
  4048.  
  4049. #
  4050. #    copy, convert, and tag input argument
  4051. #
  4052.     lea        FP_SRC(%a6),%a0
  4053.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  4054.     mov.l        0x8+0x4(%a6),0x4(%a0)
  4055.     mov.l        0x8+0x8(%a6),0x8(%a0)
  4056.     bsr.l        tag            # fetch operand type
  4057.     mov.b        %d0,STAG(%a6)
  4058.     mov.b        %d0,%d1
  4059.  
  4060.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4061.  
  4062.     clr.l        %d0
  4063.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4064.  
  4065.     tst.b        %d1
  4066.     bne.b        _L19_2x
  4067.     bsr.l        sgetman            # operand is a NORM
  4068.     bra.b        _L19_6x
  4069. _L19_2x:
  4070.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4071.     bne.b        _L19_3x            # no
  4072.     bsr.l        src_zero            # yes
  4073.     bra.b        _L19_6x
  4074. _L19_3x:
  4075.     cmpi.b        %d1,&INF        # is operand an INF?
  4076.     bne.b        _L19_4x            # no
  4077.     bsr.l        t_operr            # yes
  4078.     bra.b        _L19_6x
  4079. _L19_4x:
  4080.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4081.     bne.b        _L19_5x            # no
  4082.     bsr.l        src_qnan            # yes
  4083.     bra.b        _L19_6x
  4084. _L19_5x:
  4085.     bsr.l        sgetmand            # operand is a DENORM
  4086. _L19_6x:
  4087.  
  4088. #
  4089. #    Result is now in FP0
  4090. #
  4091.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4092.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4093.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  4094.     unlk        %a6
  4095.     rts
  4096.  
  4097.  
  4098. #########################################################################
  4099. # MONADIC TEMPLATE                            #
  4100. #########################################################################
  4101.     global        _fsincoss_
  4102. _fsincoss_:
  4103.     link        %a6,&-LOCAL_SIZE
  4104.  
  4105.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  4106.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4107.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  4108.  
  4109.     fmov.l        &0x0,%fpcr        # zero FPCR
  4110.  
  4111. #
  4112. #    copy, convert, and tag input argument
  4113. #
  4114.     fmov.s        0x8(%a6),%fp0        # load sgl input
  4115.     fmov.x        %fp0,FP_SRC(%a6)
  4116.     lea        FP_SRC(%a6),%a0
  4117.     bsr.l        tag            # fetch operand type
  4118.     mov.b        %d0,STAG(%a6)
  4119.     mov.b        %d0,%d1
  4120.  
  4121.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4122.  
  4123.     clr.l        %d0
  4124.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4125.  
  4126.     tst.b        %d1
  4127.     bne.b        _L20_2s
  4128.     bsr.l        ssincos            # operand is a NORM
  4129.     bra.b        _L20_6s
  4130. _L20_2s:
  4131.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4132.     bne.b        _L20_3s            # no
  4133.     bsr.l        ssincosz            # yes
  4134.     bra.b        _L20_6s
  4135. _L20_3s:
  4136.     cmpi.b        %d1,&INF        # is operand an INF?
  4137.     bne.b        _L20_4s            # no
  4138.     bsr.l        ssincosi            # yes
  4139.     bra.b        _L20_6s
  4140. _L20_4s:
  4141.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4142.     bne.b        _L20_5s            # no
  4143.     bsr.l        ssincosqnan            # yes
  4144.     bra.b        _L20_6s
  4145. _L20_5s:
  4146.     bsr.l        ssincosd            # operand is a DENORM
  4147. _L20_6s:
  4148.  
  4149. #
  4150. #    Result is now in FP0
  4151. #
  4152.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4153.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4154.     fmovm.x        &0x03,-(%sp)        # store off fp0/fp1
  4155.     fmovm.x        (%sp)+,&0x40        # fp0 now in fp1
  4156.     fmovm.x        (%sp)+,&0x80        # fp1 now in fp0
  4157.     unlk        %a6
  4158.     rts
  4159.  
  4160.     global        _fsincosd_
  4161. _fsincosd_:
  4162.     link        %a6,&-LOCAL_SIZE
  4163.  
  4164.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  4165.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4166.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  4167.  
  4168.     fmov.l        &0x0,%fpcr        # zero FPCR
  4169.  
  4170. #
  4171. #    copy, convert, and tag input argument
  4172. #
  4173.     fmov.d        0x8(%a6),%fp0        # load dbl input
  4174.     fmov.x        %fp0,FP_SRC(%a6)
  4175.     lea        FP_SRC(%a6),%a0
  4176.     bsr.l        tag            # fetch operand type
  4177.     mov.b        %d0,STAG(%a6)
  4178.     mov.b        %d0,%d1
  4179.  
  4180.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4181.  
  4182.     clr.l        %d0
  4183.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4184.  
  4185.     mov.b        %d1,STAG(%a6)
  4186.     tst.b        %d1
  4187.     bne.b        _L20_2d
  4188.     bsr.l        ssincos            # operand is a NORM
  4189.     bra.b        _L20_6d
  4190. _L20_2d:
  4191.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4192.     bne.b        _L20_3d            # no
  4193.     bsr.l        ssincosz            # yes
  4194.     bra.b        _L20_6d
  4195. _L20_3d:
  4196.     cmpi.b        %d1,&INF        # is operand an INF?
  4197.     bne.b        _L20_4d            # no
  4198.     bsr.l        ssincosi            # yes
  4199.     bra.b        _L20_6d
  4200. _L20_4d:
  4201.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4202.     bne.b        _L20_5d            # no
  4203.     bsr.l        ssincosqnan            # yes
  4204.     bra.b        _L20_6d
  4205. _L20_5d:
  4206.     bsr.l        ssincosd            # operand is a DENORM
  4207. _L20_6d:
  4208.  
  4209. #
  4210. #    Result is now in FP0
  4211. #
  4212.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4213.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4214.     fmovm.x        &0x03,-(%sp)        # store off fp0/fp1
  4215.     fmovm.x        (%sp)+,&0x40        # fp0 now in fp1
  4216.     fmovm.x        (%sp)+,&0x80        # fp1 now in fp0
  4217.     unlk        %a6
  4218.     rts
  4219.  
  4220.     global        _fsincosx_
  4221. _fsincosx_:
  4222.     link        %a6,&-LOCAL_SIZE
  4223.  
  4224.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  4225.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4226.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  4227.  
  4228.     fmov.l        &0x0,%fpcr        # zero FPCR
  4229.  
  4230. #
  4231. #    copy, convert, and tag input argument
  4232. #
  4233.     lea        FP_SRC(%a6),%a0
  4234.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext input
  4235.     mov.l        0x8+0x4(%a6),0x4(%a0)
  4236.     mov.l        0x8+0x8(%a6),0x8(%a0)
  4237.     bsr.l        tag            # fetch operand type
  4238.     mov.b        %d0,STAG(%a6)
  4239.     mov.b        %d0,%d1
  4240.  
  4241.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4242.  
  4243.     clr.l        %d0
  4244.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4245.  
  4246.     tst.b        %d1
  4247.     bne.b        _L20_2x
  4248.     bsr.l        ssincos            # operand is a NORM
  4249.     bra.b        _L20_6x
  4250. _L20_2x:
  4251.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4252.     bne.b        _L20_3x            # no
  4253.     bsr.l        ssincosz            # yes
  4254.     bra.b        _L20_6x
  4255. _L20_3x:
  4256.     cmpi.b        %d1,&INF        # is operand an INF?
  4257.     bne.b        _L20_4x            # no
  4258.     bsr.l        ssincosi            # yes
  4259.     bra.b        _L20_6x
  4260. _L20_4x:
  4261.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4262.     bne.b        _L20_5x            # no
  4263.     bsr.l        ssincosqnan            # yes
  4264.     bra.b        _L20_6x
  4265. _L20_5x:
  4266.     bsr.l        ssincosd            # operand is a DENORM
  4267. _L20_6x:
  4268.  
  4269. #
  4270. #    Result is now in FP0
  4271. #
  4272.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4273.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4274.     fmovm.x        &0x03,-(%sp)        # store off fp0/fp1
  4275.     fmovm.x        (%sp)+,&0x40        # fp0 now in fp1
  4276.     fmovm.x        (%sp)+,&0x80        # fp1 now in fp0
  4277.     unlk        %a6
  4278.     rts
  4279.  
  4280.  
  4281. #########################################################################
  4282. # DYADIC TEMPLATE                            #
  4283. #########################################################################
  4284.     global        _frems_
  4285. _frems_:
  4286.     link        %a6,&-LOCAL_SIZE
  4287.  
  4288.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  4289.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4290.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  4291.  
  4292.     fmov.l        &0x0,%fpcr        # zero FPCR
  4293.  
  4294. #
  4295. #    copy, convert, and tag input argument
  4296. #
  4297.     fmov.s        0x8(%a6),%fp0        # load sgl dst
  4298.     fmov.x        %fp0,FP_DST(%a6)
  4299.     lea        FP_DST(%a6),%a0
  4300.     bsr.l        tag            # fetch operand type
  4301.     mov.b        %d0,DTAG(%a6)
  4302.  
  4303.     fmov.s        0xc(%a6),%fp0        # load sgl src
  4304.     fmov.x        %fp0,FP_SRC(%a6)
  4305.     lea        FP_SRC(%a6),%a0
  4306.     bsr.l        tag            # fetch operand type
  4307.     mov.b        %d0,STAG(%a6)
  4308.     mov.l        %d0,%d1
  4309.  
  4310.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4311.  
  4312.     clr.l        %d0
  4313.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4314.  
  4315.     lea        FP_SRC(%a6),%a0        # pass ptr to src
  4316.     lea        FP_DST(%a6),%a1        # pass ptr to dst
  4317.  
  4318.     tst.b        %d1
  4319.     bne.b        _L21_2s
  4320.     bsr.l        srem_snorm            # operand is a NORM
  4321.     bra.b        _L21_6s
  4322. _L21_2s:
  4323.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4324.     bne.b        _L21_3s            # no
  4325.     bsr.l        srem_szero            # yes
  4326.     bra.b        _L21_6s
  4327. _L21_3s:
  4328.     cmpi.b        %d1,&INF        # is operand an INF?
  4329.     bne.b        _L21_4s            # no
  4330.     bsr.l        srem_sinf            # yes
  4331.     bra.b        _L21_6s
  4332. _L21_4s:
  4333.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4334.     bne.b        _L21_5s            # no
  4335.     bsr.l        sop_sqnan            # yes
  4336.     bra.b        _L21_6s
  4337. _L21_5s:
  4338.     bsr.l        srem_sdnrm            # operand is a DENORM
  4339. _L21_6s:
  4340.  
  4341. #
  4342. #    Result is now in FP0
  4343. #
  4344.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4345.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4346.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  4347.     unlk        %a6
  4348.     rts
  4349.  
  4350.     global        _fremd_
  4351. _fremd_:
  4352.     link        %a6,&-LOCAL_SIZE
  4353.  
  4354.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  4355.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4356.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  4357.  
  4358.     fmov.l        &0x0,%fpcr        # zero FPCR
  4359.  
  4360. #
  4361. #    copy, convert, and tag input argument
  4362. #
  4363.     fmov.d        0x8(%a6),%fp0        # load dbl dst
  4364.     fmov.x        %fp0,FP_DST(%a6)
  4365.     lea        FP_DST(%a6),%a0
  4366.     bsr.l        tag            # fetch operand type
  4367.     mov.b        %d0,DTAG(%a6)
  4368.  
  4369.     fmov.d        0x10(%a6),%fp0        # load dbl src
  4370.     fmov.x        %fp0,FP_SRC(%a6)
  4371.     lea        FP_SRC(%a6),%a0
  4372.     bsr.l        tag            # fetch operand type
  4373.     mov.b        %d0,STAG(%a6)
  4374.     mov.l        %d0,%d1
  4375.  
  4376.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4377.  
  4378.     clr.l        %d0
  4379.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4380.  
  4381.     lea        FP_SRC(%a6),%a0        # pass ptr to src
  4382.     lea        FP_DST(%a6),%a1        # pass ptr to dst
  4383.  
  4384.     tst.b        %d1
  4385.     bne.b        _L21_2d
  4386.     bsr.l        srem_snorm            # operand is a NORM
  4387.     bra.b        _L21_6d
  4388. _L21_2d:
  4389.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4390.     bne.b        _L21_3d            # no
  4391.     bsr.l        srem_szero            # yes
  4392.     bra.b        _L21_6d
  4393. _L21_3d:
  4394.     cmpi.b        %d1,&INF        # is operand an INF?
  4395.     bne.b        _L21_4d            # no
  4396.     bsr.l        srem_sinf            # yes
  4397.     bra.b        _L21_6d
  4398. _L21_4d:
  4399.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4400.     bne.b        _L21_5d            # no
  4401.     bsr.l        sop_sqnan            # yes
  4402.     bra.b        _L21_6d
  4403. _L21_5d:
  4404.     bsr.l        srem_sdnrm            # operand is a DENORM
  4405. _L21_6d:
  4406.  
  4407. #
  4408. #    Result is now in FP0
  4409. #
  4410.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4411.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4412.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  4413.     unlk        %a6
  4414.     rts
  4415.  
  4416.     global        _fremx_
  4417. _fremx_:
  4418.     link        %a6,&-LOCAL_SIZE
  4419.  
  4420.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  4421.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4422.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  4423.  
  4424.     fmov.l        &0x0,%fpcr        # zero FPCR
  4425.  
  4426. #
  4427. #    copy, convert, and tag input argument
  4428. #
  4429.     lea        FP_DST(%a6),%a0
  4430.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext dst
  4431.     mov.l        0x8+0x4(%a6),0x4(%a0)
  4432.     mov.l        0x8+0x8(%a6),0x8(%a0)
  4433.     bsr.l        tag            # fetch operand type
  4434.     mov.b        %d0,DTAG(%a6)
  4435.  
  4436.     lea        FP_SRC(%a6),%a0
  4437.     mov.l        0x14+0x0(%a6),0x0(%a0)    # load ext src
  4438.     mov.l        0x14+0x4(%a6),0x4(%a0)
  4439.     mov.l        0x14+0x8(%a6),0x8(%a0)
  4440.     bsr.l        tag            # fetch operand type
  4441.     mov.b        %d0,STAG(%a6)
  4442.     mov.l        %d0,%d1
  4443.  
  4444.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4445.  
  4446.     clr.l        %d0
  4447.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4448.  
  4449.     lea        FP_SRC(%a6),%a0        # pass ptr to src
  4450.     lea        FP_DST(%a6),%a1        # pass ptr to dst
  4451.  
  4452.     tst.b        %d1
  4453.     bne.b        _L21_2x
  4454.     bsr.l        srem_snorm            # operand is a NORM
  4455.     bra.b        _L21_6x
  4456. _L21_2x:
  4457.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4458.     bne.b        _L21_3x            # no
  4459.     bsr.l        srem_szero            # yes
  4460.     bra.b        _L21_6x
  4461. _L21_3x:
  4462.     cmpi.b        %d1,&INF        # is operand an INF?
  4463.     bne.b        _L21_4x            # no
  4464.     bsr.l        srem_sinf            # yes
  4465.     bra.b        _L21_6x
  4466. _L21_4x:
  4467.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4468.     bne.b        _L21_5x            # no
  4469.     bsr.l        sop_sqnan            # yes
  4470.     bra.b        _L21_6x
  4471. _L21_5x:
  4472.     bsr.l        srem_sdnrm            # operand is a DENORM
  4473. _L21_6x:
  4474.  
  4475. #
  4476. #    Result is now in FP0
  4477. #
  4478.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4479.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4480.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  4481.     unlk        %a6
  4482.     rts
  4483.  
  4484.  
  4485. #########################################################################
  4486. # DYADIC TEMPLATE                            #
  4487. #########################################################################
  4488.     global        _fmods_
  4489. _fmods_:
  4490.     link        %a6,&-LOCAL_SIZE
  4491.  
  4492.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  4493.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4494.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  4495.  
  4496.     fmov.l        &0x0,%fpcr        # zero FPCR
  4497.  
  4498. #
  4499. #    copy, convert, and tag input argument
  4500. #
  4501.     fmov.s        0x8(%a6),%fp0        # load sgl dst
  4502.     fmov.x        %fp0,FP_DST(%a6)
  4503.     lea        FP_DST(%a6),%a0
  4504.     bsr.l        tag            # fetch operand type
  4505.     mov.b        %d0,DTAG(%a6)
  4506.  
  4507.     fmov.s        0xc(%a6),%fp0        # load sgl src
  4508.     fmov.x        %fp0,FP_SRC(%a6)
  4509.     lea        FP_SRC(%a6),%a0
  4510.     bsr.l        tag            # fetch operand type
  4511.     mov.b        %d0,STAG(%a6)
  4512.     mov.l        %d0,%d1
  4513.  
  4514.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4515.  
  4516.     clr.l        %d0
  4517.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4518.  
  4519.     lea        FP_SRC(%a6),%a0        # pass ptr to src
  4520.     lea        FP_DST(%a6),%a1        # pass ptr to dst
  4521.  
  4522.     tst.b        %d1
  4523.     bne.b        _L22_2s
  4524.     bsr.l        smod_snorm            # operand is a NORM
  4525.     bra.b        _L22_6s
  4526. _L22_2s:
  4527.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4528.     bne.b        _L22_3s            # no
  4529.     bsr.l        smod_szero            # yes
  4530.     bra.b        _L22_6s
  4531. _L22_3s:
  4532.     cmpi.b        %d1,&INF        # is operand an INF?
  4533.     bne.b        _L22_4s            # no
  4534.     bsr.l        smod_sinf            # yes
  4535.     bra.b        _L22_6s
  4536. _L22_4s:
  4537.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4538.     bne.b        _L22_5s            # no
  4539.     bsr.l        sop_sqnan            # yes
  4540.     bra.b        _L22_6s
  4541. _L22_5s:
  4542.     bsr.l        smod_sdnrm            # operand is a DENORM
  4543. _L22_6s:
  4544.  
  4545. #
  4546. #    Result is now in FP0
  4547. #
  4548.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4549.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4550.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  4551.     unlk        %a6
  4552.     rts
  4553.  
  4554.     global        _fmodd_
  4555. _fmodd_:
  4556.     link        %a6,&-LOCAL_SIZE
  4557.  
  4558.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  4559.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4560.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  4561.  
  4562.     fmov.l        &0x0,%fpcr        # zero FPCR
  4563.  
  4564. #
  4565. #    copy, convert, and tag input argument
  4566. #
  4567.     fmov.d        0x8(%a6),%fp0        # load dbl dst
  4568.     fmov.x        %fp0,FP_DST(%a6)
  4569.     lea        FP_DST(%a6),%a0
  4570.     bsr.l        tag            # fetch operand type
  4571.     mov.b        %d0,DTAG(%a6)
  4572.  
  4573.     fmov.d        0x10(%a6),%fp0        # load dbl src
  4574.     fmov.x        %fp0,FP_SRC(%a6)
  4575.     lea        FP_SRC(%a6),%a0
  4576.     bsr.l        tag            # fetch operand type
  4577.     mov.b        %d0,STAG(%a6)
  4578.     mov.l        %d0,%d1
  4579.  
  4580.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4581.  
  4582.     clr.l        %d0
  4583.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4584.  
  4585.     lea        FP_SRC(%a6),%a0        # pass ptr to src
  4586.     lea        FP_DST(%a6),%a1        # pass ptr to dst
  4587.  
  4588.     tst.b        %d1
  4589.     bne.b        _L22_2d
  4590.     bsr.l        smod_snorm            # operand is a NORM
  4591.     bra.b        _L22_6d
  4592. _L22_2d:
  4593.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4594.     bne.b        _L22_3d            # no
  4595.     bsr.l        smod_szero            # yes
  4596.     bra.b        _L22_6d
  4597. _L22_3d:
  4598.     cmpi.b        %d1,&INF        # is operand an INF?
  4599.     bne.b        _L22_4d            # no
  4600.     bsr.l        smod_sinf            # yes
  4601.     bra.b        _L22_6d
  4602. _L22_4d:
  4603.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4604.     bne.b        _L22_5d            # no
  4605.     bsr.l        sop_sqnan            # yes
  4606.     bra.b        _L22_6d
  4607. _L22_5d:
  4608.     bsr.l        smod_sdnrm            # operand is a DENORM
  4609. _L22_6d:
  4610.  
  4611. #
  4612. #    Result is now in FP0
  4613. #
  4614.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4615.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4616.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  4617.     unlk        %a6
  4618.     rts
  4619.  
  4620.     global        _fmodx_
  4621. _fmodx_:
  4622.     link        %a6,&-LOCAL_SIZE
  4623.  
  4624.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  4625.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4626.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  4627.  
  4628.     fmov.l        &0x0,%fpcr        # zero FPCR
  4629.  
  4630. #
  4631. #    copy, convert, and tag input argument
  4632. #
  4633.     lea        FP_DST(%a6),%a0
  4634.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext dst
  4635.     mov.l        0x8+0x4(%a6),0x4(%a0)
  4636.     mov.l        0x8+0x8(%a6),0x8(%a0)
  4637.     bsr.l        tag            # fetch operand type
  4638.     mov.b        %d0,DTAG(%a6)
  4639.  
  4640.     lea        FP_SRC(%a6),%a0
  4641.     mov.l        0x14+0x0(%a6),0x0(%a0)    # load ext src
  4642.     mov.l        0x14+0x4(%a6),0x4(%a0)
  4643.     mov.l        0x14+0x8(%a6),0x8(%a0)
  4644.     bsr.l        tag            # fetch operand type
  4645.     mov.b        %d0,STAG(%a6)
  4646.     mov.l        %d0,%d1
  4647.  
  4648.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4649.  
  4650.     clr.l        %d0
  4651.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4652.  
  4653.     lea        FP_SRC(%a6),%a0        # pass ptr to src
  4654.     lea        FP_DST(%a6),%a1        # pass ptr to dst
  4655.  
  4656.     tst.b        %d1
  4657.     bne.b        _L22_2x
  4658.     bsr.l        smod_snorm            # operand is a NORM
  4659.     bra.b        _L22_6x
  4660. _L22_2x:
  4661.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4662.     bne.b        _L22_3x            # no
  4663.     bsr.l        smod_szero            # yes
  4664.     bra.b        _L22_6x
  4665. _L22_3x:
  4666.     cmpi.b        %d1,&INF        # is operand an INF?
  4667.     bne.b        _L22_4x            # no
  4668.     bsr.l        smod_sinf            # yes
  4669.     bra.b        _L22_6x
  4670. _L22_4x:
  4671.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4672.     bne.b        _L22_5x            # no
  4673.     bsr.l        sop_sqnan            # yes
  4674.     bra.b        _L22_6x
  4675. _L22_5x:
  4676.     bsr.l        smod_sdnrm            # operand is a DENORM
  4677. _L22_6x:
  4678.  
  4679. #
  4680. #    Result is now in FP0
  4681. #
  4682.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4683.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4684.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  4685.     unlk        %a6
  4686.     rts
  4687.  
  4688.  
  4689. #########################################################################
  4690. # DYADIC TEMPLATE                            #
  4691. #########################################################################
  4692.     global        _fscales_
  4693. _fscales_:
  4694.     link        %a6,&-LOCAL_SIZE
  4695.  
  4696.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  4697.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4698.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  4699.  
  4700.     fmov.l        &0x0,%fpcr        # zero FPCR
  4701.  
  4702. #
  4703. #    copy, convert, and tag input argument
  4704. #
  4705.     fmov.s        0x8(%a6),%fp0        # load sgl dst
  4706.     fmov.x        %fp0,FP_DST(%a6)
  4707.     lea        FP_DST(%a6),%a0
  4708.     bsr.l        tag            # fetch operand type
  4709.     mov.b        %d0,DTAG(%a6)
  4710.  
  4711.     fmov.s        0xc(%a6),%fp0        # load sgl src
  4712.     fmov.x        %fp0,FP_SRC(%a6)
  4713.     lea        FP_SRC(%a6),%a0
  4714.     bsr.l        tag            # fetch operand type
  4715.     mov.b        %d0,STAG(%a6)
  4716.     mov.l        %d0,%d1
  4717.  
  4718.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4719.  
  4720.     clr.l        %d0
  4721.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4722.  
  4723.     lea        FP_SRC(%a6),%a0        # pass ptr to src
  4724.     lea        FP_DST(%a6),%a1        # pass ptr to dst
  4725.  
  4726.     tst.b        %d1
  4727.     bne.b        _L23_2s
  4728.     bsr.l        sscale_snorm            # operand is a NORM
  4729.     bra.b        _L23_6s
  4730. _L23_2s:
  4731.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4732.     bne.b        _L23_3s            # no
  4733.     bsr.l        sscale_szero            # yes
  4734.     bra.b        _L23_6s
  4735. _L23_3s:
  4736.     cmpi.b        %d1,&INF        # is operand an INF?
  4737.     bne.b        _L23_4s            # no
  4738.     bsr.l        sscale_sinf            # yes
  4739.     bra.b        _L23_6s
  4740. _L23_4s:
  4741.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4742.     bne.b        _L23_5s            # no
  4743.     bsr.l        sop_sqnan            # yes
  4744.     bra.b        _L23_6s
  4745. _L23_5s:
  4746.     bsr.l        sscale_sdnrm            # operand is a DENORM
  4747. _L23_6s:
  4748.  
  4749. #
  4750. #    Result is now in FP0
  4751. #
  4752.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4753.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4754.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  4755.     unlk        %a6
  4756.     rts
  4757.  
  4758.     global        _fscaled_
  4759. _fscaled_:
  4760.     link        %a6,&-LOCAL_SIZE
  4761.  
  4762.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  4763.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4764.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  4765.  
  4766.     fmov.l        &0x0,%fpcr        # zero FPCR
  4767.  
  4768. #
  4769. #    copy, convert, and tag input argument
  4770. #
  4771.     fmov.d        0x8(%a6),%fp0        # load dbl dst
  4772.     fmov.x        %fp0,FP_DST(%a6)
  4773.     lea        FP_DST(%a6),%a0
  4774.     bsr.l        tag            # fetch operand type
  4775.     mov.b        %d0,DTAG(%a6)
  4776.  
  4777.     fmov.d        0x10(%a6),%fp0        # load dbl src
  4778.     fmov.x        %fp0,FP_SRC(%a6)
  4779.     lea        FP_SRC(%a6),%a0
  4780.     bsr.l        tag            # fetch operand type
  4781.     mov.b        %d0,STAG(%a6)
  4782.     mov.l        %d0,%d1
  4783.  
  4784.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4785.  
  4786.     clr.l        %d0
  4787.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4788.  
  4789.     lea        FP_SRC(%a6),%a0        # pass ptr to src
  4790.     lea        FP_DST(%a6),%a1        # pass ptr to dst
  4791.  
  4792.     tst.b        %d1
  4793.     bne.b        _L23_2d
  4794.     bsr.l        sscale_snorm            # operand is a NORM
  4795.     bra.b        _L23_6d
  4796. _L23_2d:
  4797.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4798.     bne.b        _L23_3d            # no
  4799.     bsr.l        sscale_szero            # yes
  4800.     bra.b        _L23_6d
  4801. _L23_3d:
  4802.     cmpi.b        %d1,&INF        # is operand an INF?
  4803.     bne.b        _L23_4d            # no
  4804.     bsr.l        sscale_sinf            # yes
  4805.     bra.b        _L23_6d
  4806. _L23_4d:
  4807.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4808.     bne.b        _L23_5d            # no
  4809.     bsr.l        sop_sqnan            # yes
  4810.     bra.b        _L23_6d
  4811. _L23_5d:
  4812.     bsr.l        sscale_sdnrm            # operand is a DENORM
  4813. _L23_6d:
  4814.  
  4815. #
  4816. #    Result is now in FP0
  4817. #
  4818.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4819.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4820.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  4821.     unlk        %a6
  4822.     rts
  4823.  
  4824.     global        _fscalex_
  4825. _fscalex_:
  4826.     link        %a6,&-LOCAL_SIZE
  4827.  
  4828.     movm.l        &0x0303,EXC_DREGS(%a6)    # save d0-d1/a0-a1
  4829.     fmovm.l        %fpcr,%fpsr,USER_FPCR(%a6) # save ctrl regs
  4830.     fmovm.x        &0xc0,EXC_FP0(%a6)    # save fp0/fp1
  4831.  
  4832.     fmov.l        &0x0,%fpcr        # zero FPCR
  4833.  
  4834. #
  4835. #    copy, convert, and tag input argument
  4836. #
  4837.     lea        FP_DST(%a6),%a0
  4838.     mov.l        0x8+0x0(%a6),0x0(%a0)    # load ext dst
  4839.     mov.l        0x8+0x4(%a6),0x4(%a0)
  4840.     mov.l        0x8+0x8(%a6),0x8(%a0)
  4841.     bsr.l        tag            # fetch operand type
  4842.     mov.b        %d0,DTAG(%a6)
  4843.  
  4844.     lea        FP_SRC(%a6),%a0
  4845.     mov.l        0x14+0x0(%a6),0x0(%a0)    # load ext src
  4846.     mov.l        0x14+0x4(%a6),0x4(%a0)
  4847.     mov.l        0x14+0x8(%a6),0x8(%a0)
  4848.     bsr.l        tag            # fetch operand type
  4849.     mov.b        %d0,STAG(%a6)
  4850.     mov.l        %d0,%d1
  4851.  
  4852.     andi.l        &0x00ff00ff,USER_FPSR(%a6)
  4853.  
  4854.     clr.l        %d0
  4855.     mov.b        FPCR_MODE(%a6),%d0    # pass rnd mode,prec
  4856.  
  4857.     lea        FP_SRC(%a6),%a0        # pass ptr to src
  4858.     lea        FP_DST(%a6),%a1        # pass ptr to dst
  4859.  
  4860.     tst.b        %d1
  4861.     bne.b        _L23_2x
  4862.     bsr.l        sscale_snorm            # operand is a NORM
  4863.     bra.b        _L23_6x
  4864. _L23_2x:
  4865.     cmpi.b        %d1,&ZERO        # is operand a ZERO?
  4866.     bne.b        _L23_3x            # no
  4867.     bsr.l        sscale_szero            # yes
  4868.     bra.b        _L23_6x
  4869. _L23_3x:
  4870.     cmpi.b        %d1,&INF        # is operand an INF?
  4871.     bne.b        _L23_4x            # no
  4872.     bsr.l        sscale_sinf            # yes
  4873.     bra.b        _L23_6x
  4874. _L23_4x:
  4875.     cmpi.b        %d1,&QNAN        # is operand a QNAN?
  4876.     bne.b        _L23_5x            # no
  4877.     bsr.l        sop_sqnan            # yes
  4878.     bra.b        _L23_6x
  4879. _L23_5x:
  4880.     bsr.l        sscale_sdnrm            # operand is a DENORM
  4881. _L23_6x:
  4882.  
  4883. #
  4884. #    Result is now in FP0
  4885. #
  4886.     movm.l        EXC_DREGS(%a6),&0x0303    # restore d0-d1/a0-a1
  4887.     fmovm.l        USER_FPCR(%a6),%fpcr,%fpsr # restore ctrl regs
  4888.     fmovm.x        EXC_FP1(%a6),&0x40    # restore fp1
  4889.     unlk        %a6
  4890.     rts
  4891.  
  4892.  
  4893. #########################################################################
  4894. # ssin():     computes the sine of a normalized input            #
  4895. # ssind():    computes the sine of a denormalized input            #
  4896. # scos():     computes the cosine of a normalized input            #
  4897. # scosd():    computes the cosine of a denormalized input        #
  4898. # ssincos():  computes the sine and cosine of a normalized input    #
  4899. # ssincosd(): computes the sine and cosine of a denormalized input    #
  4900. #                                    #
  4901. # INPUT *************************************************************** #
  4902. #    a0 = pointer to extended precision input            #
  4903. #    d0 = round precision,mode                    #
  4904. #                                    #
  4905. # OUTPUT ************************************************************** #
  4906. #    fp0 = sin(X) or cos(X)                         #
  4907. #                                    #
  4908. #    For ssincos(X):                            #
  4909. #    fp0 = sin(X)                            #
  4910. #    fp1 = cos(X)                            #
  4911. #                                    #
  4912. # ACCURACY and MONOTONICITY ******************************************* #
  4913. #    The returned result is within 1 ulp in 64 significant bit, i.e.    #
  4914. #    within 0.5001 ulp to 53 bits if the result is subsequently     #
  4915. #    rounded to double precision. The result is provably monotonic    #
  4916. #    in double precision.                        #
  4917. #                                    #
  4918. # ALGORITHM ***********************************************************    #
  4919. #                                    #
  4920. #    SIN and COS:                            #
  4921. #    1. If SIN is invoked, set AdjN := 0; otherwise, set AdjN := 1.    #
  4922. #                                    #
  4923. #    2. If |X| >= 15Pi or |X| < 2**(-40), go to 7.            #
  4924. #                                    #
  4925. #    3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let    #
  4926. #        k = N mod 4, so in particular, k = 0,1,2,or 3.        #
  4927. #        Overwrite k by k := k + AdjN.                #
  4928. #                                    #
  4929. #    4. If k is even, go to 6.                    #
  4930. #                                    #
  4931. #    5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j.         #
  4932. #        Return sgn*cos(r) where cos(r) is approximated by an     #
  4933. #        even polynomial in r, 1 + r*r*(B1+s*(B2+ ... + s*B8)),    #
  4934. #        s = r*r.                        #
  4935. #        Exit.                            #
  4936. #                                    #
  4937. #    6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r)    #
  4938. #        where sin(r) is approximated by an odd polynomial in r    #
  4939. #        r + r*s*(A1+s*(A2+ ... + s*A7)),    s = r*r.    #
  4940. #        Exit.                            #
  4941. #                                    #
  4942. #    7. If |X| > 1, go to 9.                        #
  4943. #                                    #
  4944. #    8. (|X|<2**(-40)) If SIN is invoked, return X;             #
  4945. #        otherwise return 1.                    #
  4946. #                                    #
  4947. #    9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi,         #
  4948. #        go back to 3.                        #
  4949. #                                    #
  4950. #    SINCOS:                                #
  4951. #    1. If |X| >= 15Pi or |X| < 2**(-40), go to 6.            #
  4952. #                                    #
  4953. #    2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let    #
  4954. #        k = N mod 4, so in particular, k = 0,1,2,or 3.        #
  4955. #                                    #
  4956. #    3. If k is even, go to 5.                    #
  4957. #                                    #
  4958. #    4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), ie.    #
  4959. #        j1 exclusive or with the l.s.b. of k.            #
  4960. #        sgn1 := (-1)**j1, sgn2 := (-1)**j2.            #
  4961. #        SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where    #
  4962. #        sin(r) and cos(r) are computed as odd and even         #
  4963. #        polynomials in r, respectively. Exit            #
  4964. #                                    #
  4965. #    5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1.            #
  4966. #        SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where    #
  4967. #        sin(r) and cos(r) are computed as odd and even         #
  4968. #        polynomials in r, respectively. Exit            #
  4969. #                                    #
  4970. #    6. If |X| > 1, go to 8.                        #
  4971. #                                    #
  4972. #    7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit.        #
  4973. #                                    #
  4974. #    8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi,         #
  4975. #        go back to 2.                        #
  4976. #                                    #
  4977. #########################################################################
  4978.  
  4979. SINA7:    long        0xBD6AAA77,0xCCC994F5
  4980. SINA6:    long        0x3DE61209,0x7AAE8DA1
  4981. SINA5:    long        0xBE5AE645,0x2A118AE4
  4982. SINA4:    long        0x3EC71DE3,0xA5341531
  4983. SINA3:    long        0xBF2A01A0,0x1A018B59,0x00000000,0x00000000
  4984. SINA2:    long        0x3FF80000,0x88888888,0x888859AF,0x00000000
  4985. SINA1:    long        0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x00000000
  4986.  
  4987. COSB8:    long        0x3D2AC4D0,0xD6011EE3
  4988. COSB7:    long        0xBDA9396F,0x9F45AC19
  4989. COSB6:    long        0x3E21EED9,0x0612C972
  4990. COSB5:    long        0xBE927E4F,0xB79D9FCF
  4991. COSB4:    long        0x3EFA01A0,0x1A01D423,0x00000000,0x00000000
  4992. COSB3:    long        0xBFF50000,0xB60B60B6,0x0B61D438,0x00000000
  4993. COSB2:    long        0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E
  4994. COSB1:    long        0xBF000000
  4995.  
  4996.     set        INARG,FP_SCR0
  4997.  
  4998.     set        X,FP_SCR0
  4999. #    set        XDCARE,X+2
  5000.     set        XFRAC,X+4
  5001.  
  5002.     set        RPRIME,FP_SCR0
  5003.     set        SPRIME,FP_SCR1
  5004.  
  5005.     set        POSNEG1,L_SCR1
  5006.     set        TWOTO63,L_SCR1
  5007.  
  5008.     set        ENDFLAG,L_SCR2
  5009.     set        INT,L_SCR2
  5010.  
  5011.     set        ADJN,L_SCR3
  5012.  
  5013. ############################################
  5014.     global        ssin
  5015. ssin:
  5016.     mov.l        &0,ADJN(%a6)        # yes; SET ADJN TO 0
  5017.     bra.b        SINBGN
  5018.  
  5019. ############################################
  5020.     global        scos
  5021. scos:
  5022.     mov.l        &1,ADJN(%a6)        # yes; SET ADJN TO 1
  5023.  
  5024. ############################################
  5025. SINBGN:
  5026. #--SAVE FPCR, FP1. CHECK IF |X| IS TOO SMALL OR LARGE
  5027.  
  5028.     fmov.x        (%a0),%fp0        # LOAD INPUT
  5029.     fmov.x        %fp0,X(%a6)        # save input at X
  5030.  
  5031. # "COMPACTIFY" X
  5032.     mov.l        (%a0),%d1        # put exp in hi word
  5033.     mov.w        4(%a0),%d1        # fetch hi(man)
  5034.     and.l        &0x7FFFFFFF,%d1        # strip sign
  5035.  
  5036.     cmpi.l        %d1,&0x3FD78000        # is |X| >= 2**(-40)?
  5037.     bge.b        SOK1            # no
  5038.     bra.w        SINSM            # yes; input is very small
  5039.  
  5040. SOK1:
  5041.     cmp.l        %d1,&0x4004BC7E        # is |X| < 15 PI?
  5042.     blt.b        SINMAIN            # no
  5043.     bra.w        SREDUCEX        # yes; input is very large
  5044.  
  5045. #--THIS IS THE USUAL CASE, |X| <= 15 PI.
  5046. #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
  5047. SINMAIN:
  5048.     fmov.x        %fp0,%fp1
  5049.     fmul.d        TWOBYPI(%pc),%fp1     # X*2/PI
  5050.  
  5051.     lea        PITBL+0x200(%pc),%a1     # TABLE OF N*PI/2, N = -32,...,32
  5052.  
  5053.     fmov.l        %fp1,INT(%a6)        # CONVERT TO INTEGER
  5054.  
  5055.     mov.l        INT(%a6),%d1        # make a copy of N
  5056.     asl.l        &4,%d1            # N *= 16
  5057.     add.l        %d1,%a1            # tbl_addr = a1 + (N*16)
  5058.  
  5059. # A1 IS THE ADDRESS OF N*PIBY2
  5060. # ...WHICH IS IN TWO PIECES Y1 & Y2
  5061.     fsub.x        (%a1)+,%fp0         # X-Y1
  5062.     fsub.s        (%a1),%fp0         # fp0 = R = (X-Y1)-Y2
  5063.  
  5064. SINCONT:
  5065. #--continuation from REDUCEX
  5066.  
  5067. #--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED
  5068.     mov.l        INT(%a6),%d1
  5069.     add.l        ADJN(%a6),%d1        # SEE IF D0 IS ODD OR EVEN
  5070.     ror.l        &1,%d1            # D0 WAS ODD IFF D0 IS NEGATIVE
  5071.     cmp.l        %d1,&0
  5072.     blt.w        COSPOLY
  5073.  
  5074. #--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
  5075. #--THEN WE RETURN    SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY
  5076. #--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + ... + SA7)))), WHERE
  5077. #--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS
  5078. #--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))])
  5079. #--WHERE T=S*S.
  5080. #--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION
  5081. #--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT.
  5082. SINPOLY:
  5083.     fmovm.x        &0x0c,-(%sp)        # save fp2/fp3
  5084.  
  5085.     fmov.x        %fp0,X(%a6)        # X IS R
  5086.     fmul.x        %fp0,%fp0        # FP0 IS S
  5087.  
  5088.     fmov.d        SINA7(%pc),%fp3
  5089.     fmov.d        SINA6(%pc),%fp2
  5090.  
  5091.     fmov.x        %fp0,%fp1
  5092.     fmul.x        %fp1,%fp1        # FP1 IS T
  5093.  
  5094.     ror.l        &1,%d1
  5095.     and.l        &0x80000000,%d1
  5096. # ...LEAST SIG. BIT OF D0 IN SIGN POSITION
  5097.     eor.l        %d1,X(%a6)        # X IS NOW R'= SGN*R
  5098.  
  5099.     fmul.x        %fp1,%fp3        # TA7
  5100.     fmul.x        %fp1,%fp2        # TA6
  5101.  
  5102.     fadd.d        SINA5(%pc),%fp3        # A5+TA7
  5103.     fadd.d        SINA4(%pc),%fp2        # A4+TA6
  5104.  
  5105.     fmul.x        %fp1,%fp3        # T(A5+TA7)
  5106.     fmul.x        %fp1,%fp2        # T(A4+TA6)
  5107.  
  5108.     fadd.d        SINA3(%pc),%fp3        # A3+T(A5+TA7)
  5109.     fadd.x        SINA2(%pc),%fp2        # A2+T(A4+TA6)
  5110.  
  5111.     fmul.x        %fp3,%fp1        # T(A3+T(A5+TA7))
  5112.  
  5113.     fmul.x        %fp0,%fp2        # S(A2+T(A4+TA6))
  5114.     fadd.x        SINA1(%pc),%fp1        # A1+T(A3+T(A5+TA7))
  5115.     fmul.x        X(%a6),%fp0        # R'*S
  5116.  
  5117.     fadd.x        %fp2,%fp1        # [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
  5118.  
  5119.     fmul.x        %fp1,%fp0        # SIN(R')-R'
  5120.  
  5121.     fmovm.x        (%sp)+,&0x30        # restore fp2/fp3
  5122.  
  5123.     fmov.l        %d0,%fpcr        # restore users round mode,prec
  5124.     fadd.x        X(%a6),%fp0        # last inst - possible exception set
  5125.     bra        t_inx2
  5126.  
  5127. #--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
  5128. #--THEN WE RETURN    SGN*COS(R). SGN*COS(R) IS COMPUTED BY
  5129. #--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + ... + SB8)))), WHERE
  5130. #--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS
  5131. #--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))])
  5132. #--WHERE T=S*S.
  5133. #--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION
  5134. #--WHILE B2 AND B3 ARE IN DOUBLE-EXTENDED FORMAT, B1 IS -1/2
  5135. #--AND IS THEREFORE STORED AS SINGLE PRECISION.
  5136. COSPOLY:
  5137.     fmovm.x        &0x0c,-(%sp)        # save fp2/fp3
  5138.  
  5139.     fmul.x        %fp0,%fp0        # FP0 IS S
  5140.  
  5141.     fmov.d        COSB8(%pc),%fp2
  5142.     fmov.d        COSB7(%pc),%fp3
  5143.  
  5144.     fmov.x        %fp0,%fp1
  5145.     fmul.x        %fp1,%fp1        # FP1 IS T
  5146.  
  5147.     fmov.x        %fp0,X(%a6)        # X IS S
  5148.     ror.l        &1,%d1
  5149.     and.l        &0x80000000,%d1
  5150. # ...LEAST SIG. BIT OF D0 IN SIGN POSITION
  5151.  
  5152.     fmul.x        %fp1,%fp2        # TB8
  5153.  
  5154.     eor.l        %d1,X(%a6)        # X IS NOW S'= SGN*S
  5155.     and.l        &0x80000000,%d1
  5156.  
  5157.     fmul.x        %fp1,%fp3        # TB7
  5158.  
  5159.     or.l        &0x3F800000,%d1        # D0 IS SGN IN SINGLE
  5160.     mov.l        %d1,POSNEG1(%a6)
  5161.  
  5162.     fadd.d        COSB6(%pc),%fp2        # B6+TB8
  5163.     fadd.d        COSB5(%pc),%fp3        # B5+TB7
  5164.  
  5165.     fmul.x        %fp1,%fp2        # T(B6+TB8)
  5166.     fmul.x        %fp1,%fp3        # T(B5+TB7)
  5167.  
  5168.     fadd.d        COSB4(%pc),%fp2        # B4+T(B6+TB8)
  5169.     fadd.x        COSB3(%pc),%fp3        # B3+T(B5+TB7)
  5170.  
  5171.     fmul.x        %fp1,%fp2        # T(B4+T(B6+TB8))
  5172.     fmul.x        %fp3,%fp1        # T(B3+T(B5+TB7))
  5173.  
  5174.     fadd.x        COSB2(%pc),%fp2        # B2+T(B4+T(B6+TB8))
  5175.     fadd.s        COSB1(%pc),%fp1        # B1+T(B3+T(B5+TB7))
  5176.  
  5177.     fmul.x        %fp2,%fp0        # S(B2+T(B4+T(B6+TB8)))
  5178.  
  5179.     fadd.x        %fp1,%fp0
  5180.  
  5181.     fmul.x        X(%a6),%fp0
  5182.  
  5183.     fmovm.x        (%sp)+,&0x30        # restore fp2/fp3
  5184.  
  5185.     fmov.l        %d0,%fpcr        # restore users round mode,prec
  5186.     fadd.s        POSNEG1(%a6),%fp0    # last inst - possible exception set
  5187.     bra        t_inx2
  5188.  
  5189. ##############################################
  5190.  
  5191. # SINe: Big OR Small?
  5192. #--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
  5193. #--IF |X| < 2**(-40), RETURN X OR 1.
  5194. SINBORS:
  5195.     cmp.l        %d1,&0x3FFF8000
  5196.     bgt.l        SREDUCEX
  5197.  
  5198. SINSM:
  5199.     mov.l        ADJN(%a6),%d1
  5200.     cmp.l        %d1,&0
  5201.     bgt.b        COSTINY
  5202.  
  5203. # here, the operation may underflow iff the precision is sgl or dbl.
  5204. # extended denorms are handled through another entry point.
  5205. SINTINY:
  5206. #    mov.w        &0x0000,XDCARE(%a6)    # JUST IN CASE
  5207.  
  5208.     fmov.l        %d0,%fpcr        # restore users round mode,prec
  5209.     mov.b        &FMOV_OP,%d1        # last inst is MOVE
  5210.     fmov.x        X(%a6),%fp0        # last inst - possible exception set
  5211.     bra        t_catch
  5212.  
  5213. COSTINY:
  5214.     fmov.s        &0x3F800000,%fp0    # fp0 = 1.0
  5215.     fmov.l        %d0,%fpcr        # restore users round mode,prec
  5216.     fadd.s         &0x80800000,%fp0    # last inst - possible exception set
  5217.     bra        t_pinx2
  5218.  
  5219. ################################################
  5220.     global        ssind
  5221. #--SIN(X) = X FOR DENORMALIZED X
  5222. ssind:
  5223.     bra        t_extdnrm
  5224.  
  5225. ############################################
  5226.     global        scosd
  5227. #--COS(X) = 1 FOR DENORMALIZED X
  5228. scosd:
  5229.     fmov.s        &0x3F800000,%fp0    # fp0 = 1.0
  5230.     bra        t_pinx2
  5231.  
  5232. ##################################################
  5233.  
  5234.     global        ssincos
  5235. ssincos:
  5236. #--SET ADJN TO 4
  5237.     mov.l        &4,ADJN(%a6)
  5238.  
  5239.     fmov.x        (%a0),%fp0        # LOAD INPUT
  5240.     fmov.x        %fp0,X(%a6)
  5241.  
  5242.     mov.l        (%a0),%d1
  5243.     mov.w        4(%a0),%d1
  5244.     and.l        &0x7FFFFFFF,%d1        # COMPACTIFY X
  5245.  
  5246.     cmp.l        %d1,&0x3FD78000        # |X| >= 2**(-40)?
  5247.     bge.b        SCOK1
  5248.     bra.w        SCSM
  5249.  
  5250. SCOK1:
  5251.     cmp.l        %d1,&0x4004BC7E        # |X| < 15 PI?
  5252.     blt.b        SCMAIN
  5253.     bra.w        SREDUCEX
  5254.  
  5255.  
  5256. #--THIS IS THE USUAL CASE, |X| <= 15 PI.
  5257. #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
  5258. SCMAIN:
  5259.     fmov.x        %fp0,%fp1
  5260.  
  5261.     fmul.d        TWOBYPI(%pc),%fp1    # X*2/PI
  5262.  
  5263.     lea        PITBL+0x200(%pc),%a1    # TABLE OF N*PI/2, N = -32,...,32
  5264.  
  5265.     fmov.l        %fp1,INT(%a6)        # CONVERT TO INTEGER
  5266.  
  5267.     mov.l        INT(%a6),%d1
  5268.     asl.l        &4,%d1
  5269.     add.l        %d1,%a1            # ADDRESS OF N*PIBY2, IN Y1, Y2
  5270.  
  5271.     fsub.x        (%a1)+,%fp0        # X-Y1
  5272.     fsub.s        (%a1),%fp0        # FP0 IS R = (X-Y1)-Y2
  5273.  
  5274. SCCONT:
  5275. #--continuation point from REDUCEX
  5276.  
  5277.     mov.l        INT(%a6),%d1
  5278.     ror.l        &1,%d1
  5279.     cmp.l        %d1,&0            # D0 < 0 IFF N IS ODD
  5280.     bge.w        NEVEN
  5281.  
  5282. SNODD:
  5283. #--REGISTERS SAVED SO FAR: D0, A0, FP2.
  5284.     fmovm.x        &0x04,-(%sp)        # save fp2
  5285.  
  5286.     fmov.x        %fp0,RPRIME(%a6)
  5287.     fmul.x        %fp0,%fp0        # FP0 IS S = R*R
  5288.     fmov.d        SINA7(%pc),%fp1        # A7
  5289.     fmov.d        COSB8(%pc),%fp2        # B8
  5290.     fmul.x        %fp0,%fp1        # SA7
  5291.     fmul.x        %fp0,%fp2        # SB8
  5292.  
  5293.     mov.l        %d2,-(%sp)
  5294.     mov.l        %d1,%d2
  5295.     ror.l        &1,%d2
  5296.     and.l        &0x80000000,%d2
  5297.     eor.l        %d1,%d2
  5298.     and.l        &0x80000000,%d2
  5299.  
  5300.     fadd.d        SINA6(%pc),%fp1        # A6+SA7
  5301.     fadd.d        COSB7(%pc),%fp2        # B7+SB8
  5302.  
  5303.     fmul.x        %fp0,%fp1        # S(A6+SA7)
  5304.     eor.l        %d2,RPRIME(%a6)
  5305.     mov.l        (%sp)+,%d2
  5306.     fmul.x        %fp0,%fp2        # S(B7+SB8)
  5307.     ror.l        &1,%d1
  5308.     and.l        &0x80000000,%d1
  5309.     mov.l        &0x3F800000,POSNEG1(%a6)
  5310.     eor.l        %d1,POSNEG1(%a6)
  5311.  
  5312.     fadd.d        SINA5(%pc),%fp1        # A5+S(A6+SA7)
  5313.     fadd.d        COSB6(%pc),%fp2        # B6+S(B7+SB8)
  5314.  
  5315.     fmul.x        %fp0,%fp1        # S(A5+S(A6+SA7))
  5316.     fmul.x        %fp0,%fp2        # S(B6+S(B7+SB8))
  5317.     fmov.x        %fp0,SPRIME(%a6)
  5318.  
  5319.     fadd.d        SINA4(%pc),%fp1        # A4+S(A5+S(A6+SA7))
  5320.     eor.l        %d1,SPRIME(%a6)
  5321.     fadd.d        COSB5(%pc),%fp2        # B5+S(B6+S(B7+SB8))
  5322.  
  5323.     fmul.x        %fp0,%fp1        # S(A4+...)
  5324.     fmul.x        %fp0,%fp2        # S(B5+...)
  5325.  
  5326.     fadd.d        SINA3(%pc),%fp1        # A3+S(A4+...)
  5327.     fadd.d        COSB4(%pc),%fp2        # B4+S(B5+...)
  5328.  
  5329.     fmul.x        %fp0,%fp1        # S(A3+...)
  5330.     fmul.x        %fp0,%fp2        # S(B4+...)
  5331.  
  5332.     fadd.x        SINA2(%pc),%fp1        # A2+S(A3+...)
  5333.     fadd.x        COSB3(%pc),%fp2        # B3+S(B4+...)
  5334.  
  5335.     fmul.x        %fp0,%fp1        # S(A2+...)
  5336.     fmul.x        %fp0,%fp2        # S(B3+...)
  5337.  
  5338.     fadd.x        SINA1(%pc),%fp1        # A1+S(A2+...)
  5339.     fadd.x        COSB2(%pc),%fp2        # B2+S(B3+...)
  5340.  
  5341.     fmul.x        %fp0,%fp1        # S(A1+...)
  5342.     fmul.x        %fp2,%fp0        # S(B2+...)
  5343.  
  5344.     fmul.x        RPRIME(%a6),%fp1    # R'S(A1+...)
  5345.     fadd.s        COSB1(%pc),%fp0        # B1+S(B2...)
  5346.     fmul.x        SPRIME(%a6),%fp0    # S'(B1+S(B2+...))
  5347.  
  5348.     fmovm.x        (%sp)+,&0x20        # restore fp2
  5349.  
  5350.     fmov.l        %d0,%fpcr
  5351.     fadd.x        RPRIME(%a6),%fp1    # COS(X)
  5352.     bsr        sto_cos            # store cosine result
  5353.     fadd.s        POSNEG1(%a6),%fp0    # SIN(X)
  5354.     bra        t_inx2
  5355.  
  5356. NEVEN:
  5357. #--REGISTERS SAVED SO FAR: FP2.
  5358.     fmovm.x        &0x04,-(%sp)        # save fp2
  5359.  
  5360.     fmov.x        %fp0,RPRIME(%a6)
  5361.     fmul.x        %fp0,%fp0        # FP0 IS S = R*R
  5362.  
  5363.     fmov.d        COSB8(%pc),%fp1        # B8
  5364.     fmov.d        SINA7(%pc),%fp2        # A7
  5365.  
  5366.     fmul.x        %fp0,%fp1        # SB8
  5367.     fmov.x        %fp0,SPRIME(%a6)
  5368.     fmul.x        %fp0,%fp2        # SA7
  5369.  
  5370.     ror.l        &1,%d1
  5371.     and.l        &0x80000000,%d1
  5372.  
  5373.     fadd.d        COSB7(%pc),%fp1        # B7+SB8
  5374.     fadd.d        SINA6(%pc),%fp2        # A6+SA7
  5375.  
  5376.     eor.l        %d1,RPRIME(%a6)
  5377.     eor.l        %d1,SPRIME(%a6)
  5378.  
  5379.     fmul.x        %fp0,%fp1        # S(B7+SB8)
  5380.  
  5381.     or.l        &0x3F800000,%d1
  5382.     mov.l        %d1,POSNEG1(%a6)
  5383.  
  5384.     fmul.x        %fp0,%fp2        # S(A6+SA7)
  5385.  
  5386.     fadd.d        COSB6(%pc),%fp1        # B6+S(B7+SB8)
  5387.     fadd.d        SINA5(%pc),%fp2        # A5+S(A6+SA7)
  5388.  
  5389.     fmul.x        %fp0,%fp1        # S(B6+S(B7+SB8))
  5390.     fmul.x        %fp0,%fp2        # S(A5+S(A6+SA7))
  5391.  
  5392.     fadd.d        COSB5(%pc),%fp1        # B5+S(B6+S(B7+SB8))
  5393.     fadd.d        SINA4(%pc),%fp2        # A4+S(A5+S(A6+SA7))
  5394.  
  5395.     fmul.x        %fp0,%fp1        # S(B5+...)
  5396.     fmul.x        %fp0,%fp2        # S(A4+...)
  5397.  
  5398.     fadd.d        COSB4(%pc),%fp1        # B4+S(B5+...)
  5399.     fadd.d        SINA3(%pc),%fp2        # A3+S(A4+...)
  5400.  
  5401.     fmul.x        %fp0,%fp1        # S(B4+...)
  5402.     fmul.x        %fp0,%fp2        # S(A3+...)
  5403.  
  5404.     fadd.x        COSB3(%pc),%fp1        # B3+S(B4+...)
  5405.     fadd.x        SINA2(%pc),%fp2        # A2+S(A3+...)
  5406.  
  5407.     fmul.x        %fp0,%fp1        # S(B3+...)
  5408.     fmul.x        %fp0,%fp2        # S(A2+...)
  5409.  
  5410.     fadd.x        COSB2(%pc),%fp1        # B2+S(B3+...)
  5411.     fadd.x        SINA1(%pc),%fp2        # A1+S(A2+...)
  5412.  
  5413.     fmul.x        %fp0,%fp1        # S(B2+...)
  5414.     fmul.x        %fp2,%fp0        # s(a1+...)
  5415.  
  5416.  
  5417.     fadd.s        COSB1(%pc),%fp1        # B1+S(B2...)
  5418.     fmul.x        RPRIME(%a6),%fp0    # R'S(A1+...)
  5419.     fmul.x        SPRIME(%a6),%fp1    # S'(B1+S(B2+...))
  5420.  
  5421.     fmovm.x        (%sp)+,&0x20        # restore fp2
  5422.  
  5423.     fmov.l        %d0,%fpcr
  5424.     fadd.s        POSNEG1(%a6),%fp1    # COS(X)
  5425.     bsr        sto_cos            # store cosine result
  5426.     fadd.x        RPRIME(%a6),%fp0    # SIN(X)
  5427.     bra        t_inx2
  5428.  
  5429. ################################################
  5430.  
  5431. SCBORS:
  5432.     cmp.l        %d1,&0x3FFF8000
  5433.     bgt.w        SREDUCEX
  5434.  
  5435. ################################################
  5436.  
  5437. SCSM:
  5438. #    mov.w        &0x0000,XDCARE(%a6)
  5439.     fmov.s        &0x3F800000,%fp1
  5440.  
  5441.     fmov.l        %d0,%fpcr
  5442.     fsub.s        &0x00800000,%fp1
  5443.     bsr        sto_cos            # store cosine result
  5444.     fmov.l        %fpcr,%d0        # d0 must have fpcr,too
  5445.     mov.b        &FMOV_OP,%d1        # last inst is MOVE
  5446.     fmov.x        X(%a6),%fp0
  5447.     bra        t_catch
  5448.  
  5449. ##############################################
  5450.  
  5451.     global        ssincosd
  5452. #--SIN AND COS OF X FOR DENORMALIZED X
  5453. ssincosd:
  5454.     mov.l        %d0,-(%sp)        # save d0
  5455.     fmov.s        &0x3F800000,%fp1
  5456.     bsr        sto_cos            # store cosine result
  5457.     mov.l        (%sp)+,%d0        # restore d0
  5458.     bra        t_extdnrm
  5459.  
  5460. ############################################
  5461.  
  5462. #--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
  5463. #--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
  5464. #--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
  5465. SREDUCEX:
  5466.     fmovm.x        &0x3c,-(%sp)        # save {fp2-fp5}
  5467.     mov.l        %d2,-(%sp)        # save d2
  5468.     fmov.s        &0x00000000,%fp1    # fp1 = 0
  5469.  
  5470. #--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
  5471. #--there is a danger of unwanted overflow in first LOOP iteration.  In this
  5472. #--case, reduce argument by one remainder step to make subsequent reduction
  5473. #--safe.
  5474.     cmp.l        %d1,&0x7ffeffff        # is arg dangerously large?
  5475.     bne.b        SLOOP            # no
  5476.  
  5477. # yes; create 2**16383*PI/2
  5478.     mov.w        &0x7ffe,FP_SCR0_EX(%a6)
  5479.     mov.l        &0xc90fdaa2,FP_SCR0_HI(%a6)
  5480.     clr.l        FP_SCR0_LO(%a6)
  5481.  
  5482. # create low half of 2**16383*PI/2 at FP_SCR1
  5483.     mov.w        &0x7fdc,FP_SCR1_EX(%a6)
  5484.     mov.l        &0x85a308d3,FP_SCR1_HI(%a6)
  5485.     clr.l        FP_SCR1_LO(%a6)
  5486.  
  5487.     ftest.x        %fp0            # test sign of argument
  5488.     fblt.w        sred_neg
  5489.  
  5490.     or.b        &0x80,FP_SCR0_EX(%a6)    # positive arg
  5491.     or.b        &0x80,FP_SCR1_EX(%a6)
  5492. sred_neg:
  5493.     fadd.x        FP_SCR0(%a6),%fp0    # high part of reduction is exact
  5494.     fmov.x        %fp0,%fp1        # save high result in fp1
  5495.     fadd.x        FP_SCR1(%a6),%fp0    # low part of reduction
  5496.     fsub.x        %fp0,%fp1        # determine low component of result
  5497.     fadd.x        FP_SCR1(%a6),%fp1    # fp0/fp1 are reduced argument.
  5498.  
  5499. #--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
  5500. #--integer quotient will be stored in N
  5501. #--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
  5502. SLOOP:
  5503.     fmov.x        %fp0,INARG(%a6)        # +-2**K * F, 1 <= F < 2
  5504.     mov.w        INARG(%a6),%d1
  5505.     mov.l        %d1,%a1            # save a copy of D0
  5506.     and.l        &0x00007FFF,%d1
  5507.     sub.l        &0x00003FFF,%d1        # d0 = K
  5508.     cmp.l        %d1,&28
  5509.     ble.b        SLASTLOOP
  5510. SCONTLOOP:
  5511.     sub.l        &27,%d1            # d0 = L := K-27
  5512.     mov.b        &0,ENDFLAG(%a6)
  5513.     bra.b        SWORK
  5514. SLASTLOOP:
  5515.     clr.l        %d1            # d0 = L := 0
  5516.     mov.b        &1,ENDFLAG(%a6)
  5517.  
  5518. SWORK:
  5519. #--FIND THE REMAINDER OF (R,r) W.R.T.    2**L * (PI/2). L IS SO CHOSEN
  5520. #--THAT    INT( X * (2/PI) / 2**(L) ) < 2**29.
  5521.  
  5522. #--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
  5523. #--2**L * (PIby2_1), 2**L * (PIby2_2)
  5524.  
  5525.     mov.l        &0x00003FFE,%d2        # BIASED EXP OF 2/PI
  5526.     sub.l        %d1,%d2            # BIASED EXP OF 2**(-L)*(2/PI)
  5527.  
  5528.     mov.l        &0xA2F9836E,FP_SCR0_HI(%a6)
  5529.     mov.l        &0x4E44152A,FP_SCR0_LO(%a6)
  5530.     mov.w        %d2,FP_SCR0_EX(%a6)    # FP_SCR0 = 2**(-L)*(2/PI)
  5531.  
  5532.     fmov.x        %fp0,%fp2
  5533.     fmul.x        FP_SCR0(%a6),%fp2    # fp2 = X * 2**(-L)*(2/PI)
  5534.  
  5535. #--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
  5536. #--FLOATING POINT FORMAT, THE TWO FMOVE'S    FMOVE.L FP <--> N
  5537. #--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
  5538. #--(SIGN(INARG)*2**63    +    FP2) - SIGN(INARG)*2**63 WILL GIVE
  5539. #--US THE DESIRED VALUE IN FLOATING POINT.
  5540.     mov.l        %a1,%d2
  5541.     swap        %d2
  5542.     and.l        &0x80000000,%d2
  5543.     or.l        &0x5F000000,%d2        # d2 = SIGN(INARG)*2**63 IN SGL
  5544.     mov.l        %d2,TWOTO63(%a6)
  5545.     fadd.s        TWOTO63(%a6),%fp2    # THE FRACTIONAL PART OF FP1 IS ROUNDED
  5546.     fsub.s        TWOTO63(%a6),%fp2    # fp2 = N
  5547. #    fint.x        %fp2
  5548.  
  5549. #--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
  5550.     mov.l        %d1,%d2            # d2 = L
  5551.  
  5552.     add.l        &0x00003FFF,%d2        # BIASED EXP OF 2**L * (PI/2)
  5553.     mov.w        %d2,FP_SCR0_EX(%a6)
  5554.     mov.l        &0xC90FDAA2,FP_SCR0_HI(%a6)
  5555.     clr.l        FP_SCR0_LO(%a6)        # FP_SCR0 = 2**(L) * Piby2_1
  5556.  
  5557.     add.l        &0x00003FDD,%d1
  5558.     mov.w        %d1,FP_SCR1_EX(%a6)
  5559.     mov.l        &0x85A308D3,FP_SCR1_HI(%a6)
  5560.     clr.l        FP_SCR1_LO(%a6)        # FP_SCR1 = 2**(L) * Piby2_2
  5561.  
  5562.     mov.b        ENDFLAG(%a6),%d1
  5563.  
  5564. #--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
  5565. #--P2 = 2**(L) * Piby2_2
  5566.     fmov.x        %fp2,%fp4        # fp4 = N
  5567.     fmul.x        FP_SCR0(%a6),%fp4    # fp4 = W = N*P1
  5568.     fmov.x        %fp2,%fp5        # fp5 = N
  5569.     fmul.x        FP_SCR1(%a6),%fp5    # fp5 = w = N*P2
  5570.     fmov.x        %fp4,%fp3        # fp3 = W = N*P1
  5571.  
  5572. #--we want P+p = W+w  but  |p| <= half ulp of P
  5573. #--Then, we need to compute  A := R-P   and  a := r-p
  5574.     fadd.x        %fp5,%fp3        # fp3 = P
  5575.     fsub.x        %fp3,%fp4        # fp4 = W-P
  5576.  
  5577.     fsub.x        %fp3,%fp0        # fp0 = A := R - P
  5578.     fadd.x        %fp5,%fp4        # fp4 = p = (W-P)+w
  5579.  
  5580.     fmov.x        %fp0,%fp3        # fp3 = A
  5581.     fsub.x        %fp4,%fp1        # fp1 = a := r - p
  5582.  
  5583. #--Now we need to normalize (A,a) to  "new (R,r)" where R+r = A+a but
  5584. #--|r| <= half ulp of R.
  5585.     fadd.x        %fp1,%fp0        # fp0 = R := A+a
  5586. #--No need to calculate r if this is the last loop
  5587.     cmp.b        %d1,&0
  5588.     bgt.w        SRESTORE
  5589.  
  5590. #--Need to calculate r
  5591.     fsub.x        %fp0,%fp3        # fp3 = A-R
  5592.     fadd.x        %fp3,%fp1        # fp1 = r := (A-R)+a
  5593.     bra.w        SLOOP
  5594.  
  5595. SRESTORE:
  5596.     fmov.l        %fp2,INT(%a6)
  5597.     mov.l        (%sp)+,%d2        # restore d2
  5598.     fmovm.x        (%sp)+,&0x3c        # restore {fp2-fp5}
  5599.  
  5600.     mov.l        ADJN(%a6),%d1
  5601.     cmp.l        %d1,&4
  5602.  
  5603.     blt.w        SINCONT
  5604.     bra.w        SCCONT
  5605.  
  5606. #########################################################################
  5607. # stan():  computes the tangent of a normalized input            #
  5608. # stand(): computes the tangent of a denormalized input            #
  5609. #                                    #
  5610. # INPUT *************************************************************** #
  5611. #    a0 = pointer to extended precision input            #
  5612. #    d0 = round precision,mode                    #
  5613. #                                    #
  5614. # OUTPUT ************************************************************** #
  5615. #    fp0 = tan(X)                            #
  5616. #                                    #
  5617. # ACCURACY and MONOTONICITY ******************************************* #
  5618. #    The returned result is within 3 ulp in 64 significant bit, i.e. #
  5619. #    within 0.5001 ulp to 53 bits if the result is subsequently    #
  5620. #    rounded to double precision. The result is provably monotonic    #
  5621. #    in double precision.                        #
  5622. #                                    #
  5623. # ALGORITHM *********************************************************** #
  5624. #                                    #
  5625. #    1. If |X| >= 15Pi or |X| < 2**(-40), go to 6.            #
  5626. #                                    #
  5627. #    2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let    #
  5628. #        k = N mod 2, so in particular, k = 0 or 1.        #
  5629. #                                    #
  5630. #    3. If k is odd, go to 5.                    #
  5631. #                                    #
  5632. #    4. (k is even) Tan(X) = tan(r) and tan(r) is approximated by a    #
  5633. #        rational function U/V where                #
  5634. #        U = r + r*s*(P1 + s*(P2 + s*P3)), and            #
  5635. #        V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))),  s = r*r.    #
  5636. #        Exit.                            #
  5637. #                                    #
  5638. #    4. (k is odd) Tan(X) = -cot(r). Since tan(r) is approximated by #
  5639. #        a rational function U/V where                #
  5640. #        U = r + r*s*(P1 + s*(P2 + s*P3)), and            #
  5641. #        V = 1 + s*(Q1 + s*(Q2 + s*(Q3 + s*Q4))), s = r*r,    #
  5642. #        -Cot(r) = -V/U. Exit.                    #
  5643. #                                    #
  5644. #    6. If |X| > 1, go to 8.                        #
  5645. #                                    #
  5646. #    7. (|X|<2**(-40)) Tan(X) = X. Exit.                #
  5647. #                                    #
  5648. #    8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back     #
  5649. #        to 2.                            #
  5650. #                                    #
  5651. #########################################################################
  5652.  
  5653. TANQ4:
  5654.     long        0x3EA0B759,0xF50F8688
  5655. TANP3:
  5656.     long        0xBEF2BAA5,0xA8924F04
  5657.  
  5658. TANQ3:
  5659.     long        0xBF346F59,0xB39BA65F,0x00000000,0x00000000
  5660.  
  5661. TANP2:
  5662.     long        0x3FF60000,0xE073D3FC,0x199C4A00,0x00000000
  5663.  
  5664. TANQ2:
  5665.     long        0x3FF90000,0xD23CD684,0x15D95FA1,0x00000000
  5666.  
  5667. TANP1:
  5668.     long        0xBFFC0000,0x8895A6C5,0xFB423BCA,0x00000000
  5669.  
  5670. TANQ1:
  5671.     long        0xBFFD0000,0xEEF57E0D,0xA84BC8CE,0x00000000
  5672.  
  5673. INVTWOPI:
  5674.     long        0x3FFC0000,0xA2F9836E,0x4E44152A,0x00000000
  5675.  
  5676. TWOPI1:
  5677.     long        0x40010000,0xC90FDAA2,0x00000000,0x00000000
  5678. TWOPI2:
  5679.     long        0x3FDF0000,0x85A308D4,0x00000000,0x00000000
  5680.  
  5681. #--N*PI/2, -32 <= N <= 32, IN A LEADING TERM IN EXT. AND TRAILING
  5682. #--TERM IN SGL. NOTE THAT PI IS 64-BIT LONG, THUS N*PI/2 IS AT
  5683. #--MOST 69 BITS LONG.
  5684. #    global        PITBL
  5685. PITBL:
  5686.     long        0xC0040000,0xC90FDAA2,0x2168C235,0x21800000
  5687.     long        0xC0040000,0xC2C75BCD,0x105D7C23,0xA0D00000
  5688.     long        0xC0040000,0xBC7EDCF7,0xFF523611,0xA1E80000
  5689.     long        0xC0040000,0xB6365E22,0xEE46F000,0x21480000
  5690.     long        0xC0040000,0xAFEDDF4D,0xDD3BA9EE,0xA1200000
  5691.     long        0xC0040000,0xA9A56078,0xCC3063DD,0x21FC0000
  5692.     long        0xC0040000,0xA35CE1A3,0xBB251DCB,0x21100000
  5693.     long        0xC0040000,0x9D1462CE,0xAA19D7B9,0xA1580000
  5694.     long        0xC0040000,0x96CBE3F9,0x990E91A8,0x21E00000
  5695.     long        0xC0040000,0x90836524,0x88034B96,0x20B00000
  5696.     long        0xC0040000,0x8A3AE64F,0x76F80584,0xA1880000
  5697.     long        0xC0040000,0x83F2677A,0x65ECBF73,0x21C40000
  5698.     long        0xC0030000,0xFB53D14A,0xA9C2F2C2,0x20000000
  5699.     long        0xC0030000,0xEEC2D3A0,0x87AC669F,0x21380000
  5700.     long        0xC0030000,0xE231D5F6,0x6595DA7B,0xA1300000
  5701.     long        0xC0030000,0xD5A0D84C,0x437F4E58,0x9FC00000
  5702.     long        0xC0030000,0xC90FDAA2,0x2168C235,0x21000000
  5703.     long        0xC0030000,0xBC7EDCF7,0xFF523611,0xA1680000
  5704.     long        0xC0030000,0xAFEDDF4D,0xDD3BA9EE,0xA0A00000
  5705.     long        0xC0030000,0xA35CE1A3,0xBB251DCB,0x20900000
  5706.     long        0xC0030000,0x96CBE3F9,0x990E91A8,0x21600000
  5707.     long        0xC0030000,0x8A3AE64F,0x76F80584,0xA1080000
  5708.     long        0xC0020000,0xFB53D14A,0xA9C2F2C2,0x1F800000
  5709.     long        0xC0020000,0xE231D5F6,0x6595DA7B,0xA0B00000
  5710.     long        0xC0020000,0xC90FDAA2,0x2168C235,0x20800000
  5711.     long        0xC0020000,0xAFEDDF4D,0xDD3BA9EE,0xA0200000
  5712.     long        0xC0020000,0x96CBE3F9,0x990E91A8,0x20E00000
  5713.     long        0xC0010000,0xFB53D14A,0xA9C2F2C2,0x1F000000
  5714.     long        0xC0010000,0xC90FDAA2,0x2168C235,0x20000000
  5715.     long        0xC0010000,0x96CBE3F9,0x990E91A8,0x20600000
  5716.     long        0xC0000000,0xC90FDAA2,0x2168C235,0x1F800000
  5717.     long        0xBFFF0000,0xC90FDAA2,0x2168C235,0x1F000000
  5718.     long        0x00000000,0x00000000,0x00000000,0x00000000
  5719.     long        0x3FFF0000,0xC90FDAA2,0x2168C235,0x9F000000
  5720.     long        0x40000000,0xC90FDAA2,0x2168C235,0x9F800000
  5721.     long        0x40010000,0x96CBE3F9,0x990E91A8,0xA0600000
  5722.     long        0x40010000,0xC90FDAA2,0x2168C235,0xA0000000
  5723.     long        0x40010000,0xFB53D14A,0xA9C2F2C2,0x9F000000
  5724.     long        0x40020000,0x96CBE3F9,0x990E91A8,0xA0E00000
  5725.     long        0x40020000,0xAFEDDF4D,0xDD3BA9EE,0x20200000
  5726.     long        0x40020000,0xC90FDAA2,0x2168C235,0xA0800000
  5727.     long        0x40020000,0xE231D5F6,0x6595DA7B,0x20B00000
  5728.     long        0x40020000,0xFB53D14A,0xA9C2F2C2,0x9F800000
  5729.     long        0x40030000,0x8A3AE64F,0x76F80584,0x21080000
  5730.     long        0x40030000,0x96CBE3F9,0x990E91A8,0xA1600000
  5731.     long        0x40030000,0xA35CE1A3,0xBB251DCB,0xA0900000
  5732.     long        0x40030000,0xAFEDDF4D,0xDD3BA9EE,0x20A00000
  5733.     long        0x40030000,0xBC7EDCF7,0xFF523611,0x21680000
  5734.     long        0x40030000,0xC90FDAA2,0x2168C235,0xA1000000
  5735.     long        0x40030000,0xD5A0D84C,0x437F4E58,0x1FC00000
  5736.     long        0x40030000,0xE231D5F6,0x6595DA7B,0x21300000
  5737.     long        0x40030000,0xEEC2D3A0,0x87AC669F,0xA1380000
  5738.     long        0x40030000,0xFB53D14A,0xA9C2F2C2,0xA0000000
  5739.     long        0x40040000,0x83F2677A,0x65ECBF73,0xA1C40000
  5740.     long        0x40040000,0x8A3AE64F,0x76F80584,0x21880000
  5741.     long        0x40040000,0x90836524,0x88034B96,0xA0B00000
  5742.     long        0x40040000,0x96CBE3F9,0x990E91A8,0xA1E00000
  5743.     long        0x40040000,0x9D1462CE,0xAA19D7B9,0x21580000
  5744.     long        0x40040000,0xA35CE1A3,0xBB251DCB,0xA1100000
  5745.     long        0x40040000,0xA9A56078,0xCC3063DD,0xA1FC0000
  5746.     long        0x40040000,0xAFEDDF4D,0xDD3BA9EE,0x21200000
  5747.     long        0x40040000,0xB6365E22,0xEE46F000,0xA1480000
  5748.     long        0x40040000,0xBC7EDCF7,0xFF523611,0x21E80000
  5749.     long        0x40040000,0xC2C75BCD,0x105D7C23,0x20D00000
  5750.     long        0x40040000,0xC90FDAA2,0x2168C235,0xA1800000
  5751.  
  5752.     set        INARG,FP_SCR0
  5753.  
  5754.     set        TWOTO63,L_SCR1
  5755.     set        INT,L_SCR1
  5756.     set        ENDFLAG,L_SCR2
  5757.  
  5758.     global        stan
  5759. stan:
  5760.     fmov.x        (%a0),%fp0        # LOAD INPUT
  5761.  
  5762.     mov.l        (%a0),%d1
  5763.     mov.w        4(%a0),%d1
  5764.     and.l        &0x7FFFFFFF,%d1
  5765.  
  5766.     cmp.l        %d1,&0x3FD78000        # |X| >= 2**(-40)?
  5767.     bge.b        TANOK1
  5768.     bra.w        TANSM
  5769. TANOK1:
  5770.     cmp.l        %d1,&0x4004BC7E        # |X| < 15 PI?
  5771.     blt.b        TANMAIN
  5772.     bra.w        REDUCEX
  5773.  
  5774. TANMAIN:
  5775. #--THIS IS THE USUAL CASE, |X| <= 15 PI.
  5776. #--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
  5777.     fmov.x        %fp0,%fp1
  5778.     fmul.d        TWOBYPI(%pc),%fp1    # X*2/PI
  5779.  
  5780.     lea.l        PITBL+0x200(%pc),%a1    # TABLE OF N*PI/2, N = -32,...,32
  5781.  
  5782.     fmov.l        %fp1,%d1        # CONVERT TO INTEGER
  5783.  
  5784.     asl.l        &4,%d1
  5785.     add.l        %d1,%a1            # ADDRESS N*PIBY2 IN Y1, Y2
  5786.  
  5787.     fsub.x        (%a1)+,%fp0        # X-Y1
  5788.  
  5789.     fsub.s        (%a1),%fp0        # FP0 IS R = (X-Y1)-Y2
  5790.  
  5791.     ror.l        &5,%d1
  5792.     and.l        &0x80000000,%d1        # D0 WAS ODD IFF D0 < 0
  5793.  
  5794. TANCONT:
  5795.     fmovm.x        &0x0c,-(%sp)        # save fp2,fp3
  5796.  
  5797.     cmp.l        %d1,&0
  5798.     blt.w        NODD
  5799.  
  5800.     fmov.x        %fp0,%fp1
  5801.     fmul.x        %fp1,%fp1        # S = R*R
  5802.  
  5803.     fmov.d        TANQ4(%pc),%fp3
  5804.     fmov.d        TANP3(%pc),%fp2
  5805.  
  5806.     fmul.x        %fp1,%fp3        # SQ4
  5807.     fmul.x        %fp1,%fp2        # SP3
  5808.  
  5809.     fadd.d        TANQ3(%pc),%fp3        # Q3+SQ4
  5810.     fadd.x        TANP2(%pc),%fp2        # P2+SP3
  5811.  
  5812.     fmul.x        %fp1,%fp3        # S(Q3+SQ4)
  5813.     fmul.x        %fp1,%fp2        # S(P2+SP3)
  5814.  
  5815.     fadd.x        TANQ2(%pc),%fp3        # Q2+S(Q3+SQ4)
  5816.     fadd.x        TANP1(%pc),%fp2        # P1+S(P2+SP3)
  5817.  
  5818.     fmul.x        %fp1,%fp3        # S(Q2+S(Q3+SQ4))
  5819.     fmul.x        %fp1,%fp2        # S(P1+S(P2+SP3))
  5820.  
  5821.     fadd.x        TANQ1(%pc),%fp3        # Q1+S(Q2+S(Q3+SQ4))
  5822.     fmul.x        %fp0,%fp2        # RS(P1+S(P2+SP3))
  5823.  
  5824.     fmul.x        %fp3,%fp1        # S(Q1+S(Q2+S(Q3+SQ4)))
  5825.  
  5826.     fadd.x        %fp2,%fp0        # R+RS(P1+S(P2+SP3))
  5827.  
  5828.     fadd.s        &0x3F800000,%fp1    # 1+S(Q1+...)
  5829.  
  5830.     fmovm.x        (%sp)+,&0x30        # restore fp2,fp3
  5831.  
  5832.     fmov.l        %d0,%fpcr        # restore users round mode,prec
  5833.     fdiv.x        %fp1,%fp0        # last inst - possible exception set
  5834.     bra        t_inx2
  5835.  
  5836. NODD:
  5837.     fmov.x        %fp0,%fp1
  5838.     fmul.x        %fp0,%fp0        # S = R*R
  5839.  
  5840.     fmov.d        TANQ4(%pc),%fp3
  5841.     fmov.d        TANP3(%pc),%fp2
  5842.  
  5843.     fmul.x        %fp0,%fp3        # SQ4
  5844.     fmul.x        %fp0,%fp2        # SP3
  5845.  
  5846.     fadd.d        TANQ3(%pc),%fp3        # Q3+SQ4
  5847.     fadd.x        TANP2(%pc),%fp2        # P2+SP3
  5848.  
  5849.     fmul.x        %fp0,%fp3        # S(Q3+SQ4)
  5850.     fmul.x        %fp0,%fp2        # S(P2+SP3)
  5851.  
  5852.     fadd.x        TANQ2(%pc),%fp3        # Q2+S(Q3+SQ4)
  5853.     fadd.x        TANP1(%pc),%fp2        # P1+S(P2+SP3)
  5854.  
  5855.     fmul.x        %fp0,%fp3        # S(Q2+S(Q3+SQ4))
  5856.     fmul.x        %fp0,%fp2        # S(P1+S(P2+SP3))
  5857.  
  5858.     fadd.x        TANQ1(%pc),%fp3        # Q1+S(Q2+S(Q3+SQ4))
  5859.     fmul.x        %fp1,%fp2        # RS(P1+S(P2+SP3))
  5860.  
  5861.     fmul.x        %fp3,%fp0        # S(Q1+S(Q2+S(Q3+SQ4)))
  5862.  
  5863.     fadd.x        %fp2,%fp1        # R+RS(P1+S(P2+SP3))
  5864.     fadd.s        &0x3F800000,%fp0    # 1+S(Q1+...)
  5865.  
  5866.     fmovm.x        (%sp)+,&0x30        # restore fp2,fp3
  5867.  
  5868.     fmov.x        %fp1,-(%sp)
  5869.     eor.l        &0x80000000,(%sp)
  5870.  
  5871.     fmov.l        %d0,%fpcr        # restore users round mode,prec
  5872.     fdiv.x        (%sp)+,%fp0        # last inst - possible exception set
  5873.     bra        t_inx2
  5874.  
  5875. TANBORS:
  5876. #--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
  5877. #--IF |X| < 2**(-40), RETURN X OR 1.
  5878.     cmp.l        %d1,&0x3FFF8000
  5879.     bgt.b        REDUCEX
  5880.  
  5881. TANSM:
  5882.     fmov.x        %fp0,-(%sp)
  5883.     fmov.l        %d0,%fpcr        # restore users round mode,prec
  5884.     mov.b        &FMOV_OP,%d1        # last inst is MOVE
  5885.     fmov.x        (%sp)+,%fp0        # last inst - posibble exception set
  5886.     bra        t_catch
  5887.  
  5888.     global        stand
  5889. #--TAN(X) = X FOR DENORMALIZED X
  5890. stand:
  5891.     bra        t_extdnrm
  5892.  
  5893. #--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
  5894. #--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
  5895. #--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
  5896. REDUCEX:
  5897.     fmovm.x        &0x3c,-(%sp)        # save {fp2-fp5}
  5898.     mov.l        %d2,-(%sp)        # save d2
  5899.     fmov.s        &0x00000000,%fp1    # fp1 = 0
  5900.  
  5901. #--If compact form of abs(arg) in d0=$7ffeffff, argument is so large that
  5902. #--there is a danger of unwanted overflow in first LOOP iteration.  In this
  5903. #--case, reduce argument by one remainder step to make subsequent reduction
  5904. #--safe.
  5905.     cmp.l        %d1,&0x7ffeffff        # is arg dangerously large?
  5906.     bne.b        LOOP            # no
  5907.  
  5908. # yes; create 2**16383*PI/2
  5909.     mov.w        &0x7ffe,FP_SCR0_EX(%a6)
  5910.     mov.l        &0xc90fdaa2,FP_SCR0_HI(%a6)
  5911.     clr.l        FP_SCR0_LO(%a6)
  5912.  
  5913. # create low half of 2**16383*PI/2 at FP_SCR1
  5914.     mov.w        &0x7fdc,FP_SCR1_EX(%a6)
  5915.     mov.l        &0x85a308d3,FP_SCR1_HI(%a6)
  5916.     clr.l        FP_SCR1_LO(%a6)
  5917.  
  5918.     ftest.x        %fp0            # test sign of argument
  5919.     fblt.w        red_neg
  5920.  
  5921.     or.b        &0x80,FP_SCR0_EX(%a6)    # positive arg
  5922.     or.b        &0x80,FP_SCR1_EX(%a6)
  5923. red_neg:
  5924.     fadd.x        FP_SCR0(%a6),%fp0    # high part of reduction is exact
  5925.     fmov.x        %fp0,%fp1        # save high result in fp1
  5926.     fadd.x        FP_SCR1(%a6),%fp0    # low part of reduction
  5927.     fsub.x        %fp0,%fp1        # determine low component of result
  5928.     fadd.x        FP_SCR1(%a6),%fp1    # fp0/fp1 are reduced argument.
  5929.  
  5930. #--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
  5931. #--integer quotient will be stored in N
  5932. #--Intermeditate remainder is 66-bit long; (R,r) in (FP0,FP1)
  5933. LOOP:
  5934.     fmov.x        %fp0,INARG(%a6)        # +-2**K * F, 1 <= F < 2
  5935.     mov.w        INARG(%a6),%d1
  5936.     mov.l        %d1,%a1            # save a copy of D0
  5937.     and.l        &0x00007FFF,%d1
  5938.     sub.l        &0x00003FFF,%d1        # d0 = K
  5939.     cmp.l        %d1,&28
  5940.     ble.b        LASTLOOP
  5941. CONTLOOP:
  5942.     sub.l        &27,%d1            # d0 = L := K-27
  5943.     mov.b        &0,ENDFLAG(%a6)
  5944.     bra.b        WORK
  5945. LASTLOOP:
  5946.     clr.l        %d1            # d0 = L := 0
  5947.     mov.b        &1,ENDFLAG(%a6)
  5948.  
  5949. WORK:
  5950. #--FIND THE REMAINDER OF (R,r) W.R.T.    2**L * (PI/2). L IS SO CHOSEN
  5951. #--THAT    INT( X * (2/PI) / 2**(L) ) < 2**29.
  5952.  
  5953. #--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
  5954. #--2**L * (PIby2_1), 2**L * (PIby2_2)
  5955.  
  5956.     mov.l        &0x00003FFE,%d2        # BIASED EXP OF 2/PI
  5957.     sub.l        %d1,%d2            # BIASED EXP OF 2**(-L)*(2/PI)
  5958.  
  5959.     mov.l        &0xA2F9836E,FP_SCR0_HI(%a6)
  5960.     mov.l        &0x4E44152A,FP_SCR0_LO(%a6)
  5961.     mov.w        %d2,FP_SCR0_EX(%a6)    # FP_SCR0 = 2**(-L)*(2/PI)
  5962.  
  5963.     fmov.x        %fp0,%fp2
  5964.     fmul.x        FP_SCR0(%a6),%fp2    # fp2 = X * 2**(-L)*(2/PI)
  5965.  
  5966. #--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
  5967. #--FLOATING POINT FORMAT, THE TWO FMOVE'S    FMOVE.L FP <--> N
  5968. #--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
  5969. #--(SIGN(INARG)*2**63    +    FP2) - SIGN(INARG)*2**63 WILL GIVE
  5970. #--US THE DESIRED VALUE IN FLOATING POINT.
  5971.     mov.l        %a1,%d2
  5972.     swap        %d2
  5973.     and.l        &0x80000000,%d2
  5974.     or.l        &0x5F000000,%d2        # d2 = SIGN(INARG)*2**63 IN SGL
  5975.     mov.l        %d2,TWOTO63(%a6)
  5976.     fadd.s        TWOTO63(%a6),%fp2    # THE FRACTIONAL PART OF FP1 IS ROUNDED
  5977.     fsub.s        TWOTO63(%a6),%fp2    # fp2 = N
  5978. #    fintrz.x    %fp2,%fp2
  5979.  
  5980. #--CREATING 2**(L)*Piby2_1 and 2**(L)*Piby2_2
  5981.     mov.l        %d1,%d2            # d2 = L
  5982.  
  5983.     add.l        &0x00003FFF,%d2        # BIASED EXP OF 2**L * (PI/2)
  5984.     mov.w        %d2,FP_SCR0_EX(%a6)
  5985.     mov.l        &0xC90FDAA2,FP_SCR0_HI(%a6)
  5986.     clr.l        FP_SCR0_LO(%a6)        # FP_SCR0 = 2**(L) * Piby2_1
  5987.  
  5988.     add.l        &0x00003FDD,%d1
  5989.     mov.w        %d1,FP_SCR1_EX(%a6)
  5990.     mov.l        &0x85A308D3,FP_SCR1_HI(%a6)
  5991.     clr.l        FP_SCR1_LO(%a6)        # FP_SCR1 = 2**(L) * Piby2_2
  5992.  
  5993.     mov.b        ENDFLAG(%a6),%d1
  5994.  
  5995. #--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
  5996. #--P2 = 2**(L) * Piby2_2
  5997.     fmov.x        %fp2,%fp4        # fp4 = N
  5998.     fmul.x        FP_SCR0(%a6),%fp4    # fp4 = W = N*P1
  5999.     fmov.x        %fp2,%fp5        # fp5 = N
  6000.     fmul.x        FP_SCR1(%a6),%fp5    # fp5 = w = N*P2
  6001.     fmov.x        %fp4,%fp3        # fp3 = W = N*P1
  6002.  
  6003. #--we want P+p = W+w  but  |p| <= half ulp of P
  6004. #--Then, we need to compute  A := R-P   and  a := r-p
  6005.     fadd.x        %fp5,%fp3        # fp3 = P
  6006.     fsub.x        %fp3,%fp4        # fp4 = W-P
  6007.  
  6008.     fsub.x        %fp3,%fp0        # fp0 = A := R - P
  6009.     fadd.x        %fp5,%fp4        # fp4 = p = (W-P)+w
  6010.  
  6011.     fmov.x        %fp0,%fp3        # fp3 = A
  6012.     fsub.x        %fp4,%fp1        # fp1 = a := r - p
  6013.  
  6014. #--Now we need to normalize (A,a) to  "new (R,r)" where R+r = A+a but
  6015. #--|r| <= half ulp of R.
  6016.     fadd.x        %fp1,%fp0        # fp0 = R := A+a
  6017. #--No need to calculate r if this is the last loop
  6018.     cmp.b        %d1,&0
  6019.     bgt.w        RESTORE
  6020.  
  6021. #--Need to calculate r
  6022.     fsub.x        %fp0,%fp3        # fp3 = A-R
  6023.     fadd.x        %fp3,%fp1        # fp1 = r := (A-R)+a
  6024.     bra.w        LOOP
  6025.  
  6026. RESTORE:
  6027.     fmov.l        %fp2,INT(%a6)
  6028.     mov.l        (%sp)+,%d2        # restore d2
  6029.     fmovm.x        (%sp)+,&0x3c        # restore {fp2-fp5}
  6030.  
  6031.     mov.l        INT(%a6),%d1
  6032.     ror.l        &1,%d1
  6033.  
  6034.     bra.w        TANCONT
  6035.  
  6036. #########################################################################
  6037. # satan():  computes the arctangent of a normalized number        #
  6038. # satand(): computes the arctangent of a denormalized number        #
  6039. #                                    #
  6040. # INPUT    *************************************************************** #
  6041. #    a0 = pointer to extended precision input            #
  6042. #    d0 = round precision,mode                    #
  6043. #                                    #
  6044. # OUTPUT ************************************************************** #
  6045. #    fp0 = arctan(X)                            #
  6046. #                                    #
  6047. # ACCURACY and MONOTONICITY ******************************************* #
  6048. #    The returned result is within 2 ulps in    64 significant bit,    #
  6049. #    i.e. within 0.5001 ulp to 53 bits if the result is subsequently    #
  6050. #    rounded to double precision. The result is provably monotonic    #
  6051. #    in double precision.                         #
  6052. #                                    #
  6053. # ALGORITHM *********************************************************** #
  6054. #    Step 1. If |X| >= 16 or |X| < 1/16, go to Step 5.        #
  6055. #                                    #
  6056. #    Step 2. Let X = sgn * 2**k * 1.xxxxxxxx...x.             #
  6057. #        Note that k = -4, -3,..., or 3.                #
  6058. #        Define F = sgn * 2**k * 1.xxxx1, i.e. the first 5     #
  6059. #        significant bits of X with a bit-1 attached at the 6-th    #
  6060. #        bit position. Define u to be u = (X-F) / (1 + X*F).    #
  6061. #                                    #
  6062. #    Step 3. Approximate arctan(u) by a polynomial poly.        #
  6063. #                                    #
  6064. #    Step 4. Return arctan(F) + poly, arctan(F) is fetched from a     #
  6065. #        table of values calculated beforehand. Exit.        #
  6066. #                                    #
  6067. #    Step 5. If |X| >= 16, go to Step 7.                #
  6068. #                                    #
  6069. #    Step 6. Approximate arctan(X) by an odd polynomial in X. Exit.    #
  6070. #                                    #
  6071. #    Step 7. Define X' = -1/X. Approximate arctan(X') by an odd     #
  6072. #        polynomial in X'.                    #
  6073. #        Arctan(X) = sign(X)*Pi/2 + arctan(X'). Exit.        #
  6074. #                                    #
  6075. #########################################################################
  6076.  
  6077. ATANA3:    long        0xBFF6687E,0x314987D8
  6078. ATANA2:    long        0x4002AC69,0x34A26DB3
  6079. ATANA1:    long        0xBFC2476F,0x4E1DA28E
  6080.  
  6081. ATANB6:    long        0x3FB34444,0x7F876989
  6082. ATANB5:    long        0xBFB744EE,0x7FAF45DB
  6083. ATANB4:    long        0x3FBC71C6,0x46940220
  6084. ATANB3:    long        0xBFC24924,0x921872F9
  6085. ATANB2:    long        0x3FC99999,0x99998FA9
  6086. ATANB1:    long        0xBFD55555,0x55555555
  6087.  
  6088. ATANC5:    long        0xBFB70BF3,0x98539E6A
  6089. ATANC4:    long        0x3FBC7187,0x962D1D7D
  6090. ATANC3:    long        0xBFC24924,0x827107B8
  6091. ATANC2:    long        0x3FC99999,0x9996263E
  6092. ATANC1:    long        0xBFD55555,0x55555536
  6093.  
  6094. PPIBY2:    long        0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
  6095. NPIBY2:    long        0xBFFF0000,0xC90FDAA2,0x2168C235,0x00000000
  6096.  
  6097. PTINY:    long        0x00010000,0x80000000,0x00000000,0x00000000
  6098. NTINY:    long        0x80010000,0x80000000,0x00000000,0x00000000
  6099.  
  6100. ATANTBL:
  6101.     long        0x3FFB0000,0x83D152C5,0x060B7A51,0x00000000
  6102.     long        0x3FFB0000,0x8BC85445,0x65498B8B,0x00000000
  6103.     long        0x3FFB0000,0x93BE4060,0x17626B0D,0x00000000
  6104.     long        0x3FFB0000,0x9BB3078D,0x35AEC202,0x00000000
  6105.     long        0x3FFB0000,0xA3A69A52,0x5DDCE7DE,0x00000000
  6106.     long        0x3FFB0000,0xAB98E943,0x62765619,0x00000000
  6107.     long        0x3FFB0000,0xB389E502,0xF9C59862,0x00000000
  6108.     long        0x3FFB0000,0xBB797E43,0x6B09E6FB,0x00000000
  6109.     long        0x3FFB0000,0xC367A5C7,0x39E5F446,0x00000000
  6110.     long        0x3FFB0000,0xCB544C61,0xCFF7D5C6,0x00000000
  6111.     long        0x3FFB0000,0xD33F62F8,0x2488533E,0x00000000
  6112.     long        0x3FFB0000,0xDB28DA81,0x62404C77,0x00000000
  6113.     long        0x3FFB0000,0xE310A407,0x8AD34F18,0x00000000
  6114.     long        0x3FFB0000,0xEAF6B0A8,0x188EE1EB,0x00000000
  6115.     long        0x3FFB0000,0xF2DAF194,0x9DBE79D5,0x00000000
  6116.     long        0x3FFB0000,0xFABD5813,0x61D47E3E,0x00000000
  6117.     long        0x3FFC0000,0x8346AC21,0x0959ECC4,0x00000000
  6118.     long        0x3FFC0000,0x8B232A08,0x304282D8,0x00000000
  6119.     long        0x3FFC0000,0x92FB70B8,0xD29AE2F9,0x00000000
  6120.     long        0x3FFC0000,0x9ACF476F,0x5CCD1CB4,0x00000000
  6121.     long        0x3FFC0000,0xA29E7630,0x4954F23F,0x00000000
  6122.     long        0x3FFC0000,0xAA68C5D0,0x8AB85230,0x00000000
  6123.     long        0x3FFC0000,0xB22DFFFD,0x9D539F83,0x00000000
  6124.     long        0x3FFC0000,0xB9EDEF45,0x3E900EA5,0x00000000
  6125.     long        0x3FFC0000,0xC1A85F1C,0xC75E3EA5,0x00000000
  6126.     long        0x3FFC0000,0xC95D1BE8,0x28138DE6,0x00000000
  6127.     long        0x3FFC0000,0xD10BF300,0x840D2DE4,0x00000000
  6128.     long        0x3FFC0000,0xD8B4B2BA,0x6BC05E7A,0x00000000
  6129.     long        0x3FFC0000,0xE0572A6B,0xB42335F6,0x00000000
  6130.     long        0x3FFC0000,0xE7F32A70,0xEA9CAA8F,0x00000000
  6131.     long        0x3FFC0000,0xEF888432,0x64ECEFAA,0x00000000
  6132.     long        0x3FFC0000,0xF7170A28,0xECC06666,0x00000000
  6133.     long        0x3FFD0000,0x812FD288,0x332DAD32,0x00000000
  6134.     long        0x3FFD0000,0x88A8D1B1,0x218E4D64,0x00000000
  6135.     long        0x3FFD0000,0x9012AB3F,0x23E4AEE8,0x00000000
  6136.     long        0x3FFD0000,0x976CC3D4,0x11E7F1B9,0x00000000
  6137.     long        0x3FFD0000,0x9EB68949,0x3889A227,0x00000000
  6138.     long        0x3FFD0000,0xA5EF72C3,0x4487361B,0x00000000
  6139.     long        0x3FFD0000,0xAD1700BA,0xF07A7227,0x00000000
  6140.     long        0x3FFD0000,0xB42CBCFA,0xFD37EFB7,0x00000000
  6141.     long        0x3FFD0000,0xBB303A94,0x0BA80F89,0x00000000
  6142.     long        0x3FFD0000,0xC22115C6,0xFCAEBBAF,0x00000000
  6143.     long        0x3FFD0000,0xC8FEF3E6,0x86331221,0x00000000
  6144.     long        0x3FFD0000,0xCFC98330,0xB4000C70,0x00000000
  6145.     long        0x3FFD0000,0xD6807AA1,0x102C5BF9,0x00000000
  6146.     long        0x3FFD0000,0xDD2399BC,0x31252AA3,0x00000000
  6147.     long        0x3FFD0000,0xE3B2A855,0x6B8FC517,0x00000000
  6148.     long        0x3FFD0000,0xEA2D764F,0x64315989,0x00000000
  6149.     long        0x3FFD0000,0xF3BF5BF8,0xBAD1A21D,0x00000000
  6150.     long        0x3FFE0000,0x801CE39E,0x0D205C9A,0x00000000
  6151.     long        0x3FFE0000,0x8630A2DA,0xDA1ED066,0x00000000
  6152.     long        0x3FFE0000,0x8C1AD445,0xF3E09B8C,0x00000000
  6153.     long        0x3FFE0000,0x91DB8F16,0x64F350E2,0x00000000
  6154.     long        0x3FFE0000,0x97731420,0x365E538C,0x00000000
  6155.     long        0x3FFE0000,0x9CE1C8E6,0xA0B8CDBA,0x00000000
  6156.     long        0x3FFE0000,0xA22832DB,0xCADAAE09,0x00000000
  6157.     long        0x3FFE0000,0xA746F2DD,0xB7602294,0x00000000
  6158.     long        0x3FFE0000,0xAC3EC0FB,0x997DD6A2,0x00000000
  6159.     long        0x3FFE0000,0xB110688A,0xEBDC6F6A,0x00000000
  6160.     long        0x3FFE0000,0xB5BCC490,0x59ECC4B0,0x00000000
  6161.     long        0x3FFE0000,0xBA44BC7D,0xD470782F,0x00000000
  6162.     long        0x3FFE0000,0xBEA94144,0xFD049AAC,0x00000000
  6163.     long        0x3FFE0000,0xC2EB4ABB,0x661628B6,0x00000000
  6164.     long        0x3FFE0000,0xC70BD54C,0xE602EE14,0x00000000
  6165.     long        0x3FFE0000,0xCD000549,0xADEC7159,0x00000000
  6166.     long        0x3FFE0000,0xD48457D2,0xD8EA4EA3,0x00000000
  6167.     long        0x3FFE0000,0xDB948DA7,0x12DECE3B,0x00000000
  6168.     long        0x3FFE0000,0xE23855F9,0x69E8096A,0x00000000
  6169.     long        0x3FFE0000,0xE8771129,0xC4353259,0x00000000
  6170.     long        0x3FFE0000,0xEE57C16E,0x0D379C0D,0x00000000
  6171.     long        0x3FFE0000,0xF3E10211,0xA87C3779,0x00000000
  6172.     long        0x3FFE0000,0xF919039D,0x758B8D41,0x00000000
  6173.     long        0x3FFE0000,0xFE058B8F,0x64935FB3,0x00000000
  6174.     long        0x3FFF0000,0x8155FB49,0x7B685D04,0x00000000
  6175.     long        0x3FFF0000,0x83889E35,0x49D108E1,0x00000000
  6176.     long        0x3FFF0000,0x859CFA76,0x511D724B,0x00000000
  6177.     long        0x3FFF0000,0x87952ECF,0xFF8131E7,0x00000000
  6178.     long        0x3FFF0000,0x89732FD1,0x9557641B,0x00000000
  6179.     long        0x3FFF0000,0x8B38CAD1,0x01932A35,0x00000000
  6180.     long        0x3FFF0000,0x8CE7A8D8,0x301EE6B5,0x00000000
  6181.     long        0x3FFF0000,0x8F46A39E,0x2EAE5281,0x00000000
  6182.     long        0x3FFF0000,0x922DA7D7,0x91888487,0x00000000
  6183.     long        0x3FFF0000,0x94D19FCB,0xDEDF5241,0x00000000
  6184.     long        0x3FFF0000,0x973AB944,0x19D2A08B,0x00000000
  6185.     long        0x3FFF0000,0x996FF00E,0x08E10B96,0x00000000
  6186.     long        0x3FFF0000,0x9B773F95,0x12321DA7,0x00000000
  6187.     long        0x3FFF0000,0x9D55CC32,0x0F935624,0x00000000
  6188.     long        0x3FFF0000,0x9F100575,0x006CC571,0x00000000
  6189.     long        0x3FFF0000,0xA0A9C290,0xD97CC06C,0x00000000
  6190.     long        0x3FFF0000,0xA22659EB,0xEBC0630A,0x00000000
  6191.     long        0x3FFF0000,0xA388B4AF,0xF6EF0EC9,0x00000000
  6192.     long        0x3FFF0000,0xA4D35F10,0x61D292C4,0x00000000
  6193.     long        0x3FFF0000,0xA60895DC,0xFBE3187E,0x00000000
  6194.     long        0x3FFF0000,0xA72A51DC,0x7367BEAC,0x00000000
  6195.     long        0x3FFF0000,0xA83A5153,0x0956168F,0x00000000
  6196.     long        0x3FFF0000,0xA93A2007,0x7539546E,0x00000000
  6197.     long        0x3FFF0000,0xAA9E7245,0x023B2605,0x00000000
  6198.     long        0x3FFF0000,0xAC4C84BA,0x6FE4D58F,0x00000000
  6199.     long        0x3FFF0000,0xADCE4A4A,0x606B9712,0x00000000
  6200.     long        0x3FFF0000,0xAF2A2DCD,0x8D263C9C,0x00000000
  6201.     long        0x3FFF0000,0xB0656F81,0xF22265C7,0x00000000
  6202.     long        0x3FFF0000,0xB1846515,0x0F71496A,0x00000000
  6203.     long        0x3FFF0000,0xB28AAA15,0x6F9ADA35,0x00000000
  6204.     long        0x3FFF0000,0xB37B44FF,0x3766B895,0x00000000
  6205.     long        0x3FFF0000,0xB458C3DC,0xE9630433,0x00000000
  6206.     long        0x3FFF0000,0xB525529D,0x562246BD,0x00000000
  6207.     long        0x3FFF0000,0xB5E2CCA9,0x5F9D88CC,0x00000000
  6208.     long        0x3FFF0000,0xB692CADA,0x7ACA1ADA,0x00000000
  6209.     long        0x3FFF0000,0xB736AEA7,0xA6925838,0x00000000
  6210.     long        0x3FFF0000,0xB7CFAB28,0x7E9F7B36,0x00000000
  6211.     long        0x3FFF0000,0xB85ECC66,0xCB219835,0x00000000
  6212.     long        0x3FFF0000,0xB8E4FD5A,0x20A593DA,0x00000000
  6213.     long        0x3FFF0000,0xB99F41F6,0x4AFF9BB5,0x00000000
  6214.     long        0x3FFF0000,0xBA7F1E17,0x842BBE7B,0x00000000
  6215.     long        0x3FFF0000,0xBB471285,0x7637E17D,0x00000000
  6216.     long        0x3FFF0000,0xBBFABE8A,0x4788DF6F,0x00000000
  6217.     long        0x3FFF0000,0xBC9D0FAD,0x2B689D79,0x00000000
  6218.     long        0x3FFF0000,0xBD306A39,0x471ECD86,0x00000000
  6219.     long        0x3FFF0000,0xBDB6C731,0x856AF18A,0x00000000
  6220.     long        0x3FFF0000,0xBE31CAC5,0x02E80D70,0x00000000
  6221.     long        0x3FFF0000,0xBEA2D55C,0xE33194E2,0x00000000
  6222.     long        0x3FFF0000,0xBF0B10B7,0xC03128F0,0x00000000
  6223.     long        0x3FFF0000,0xBF6B7A18,0xDACB778D,0x00000000
  6224.     long        0x3FFF0000,0xBFC4EA46,0x63FA18F6,0x00000000
  6225.     long        0x3FFF0000,0xC0181BDE,0x8B89A454,0x00000000
  6226.     long        0x3FFF0000,0xC065B066,0xCFBF6439,0x00000000
  6227.     long        0x3FFF0000,0xC0AE345F,0x56340AE6,0x00000000
  6228.     long        0x3FFF0000,0xC0F22291,0x9CB9E6A7,0x00000000
  6229.  
  6230.     set        X,FP_SCR0
  6231.     set        XDCARE,X+2
  6232.     set        XFRAC,X+4
  6233.     set        XFRACLO,X+8
  6234.  
  6235.     set        ATANF,FP_SCR1
  6236.     set        ATANFHI,ATANF+4
  6237.     set        ATANFLO,ATANF+8
  6238.  
  6239.     global        satan
  6240. #--ENTRY POINT FOR ATAN(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
  6241. satan:
  6242.     fmov.x        (%a0),%fp0        # LOAD INPUT
  6243.  
  6244.     mov.l        (%a0),%d1
  6245.     mov.w        4(%a0),%d1
  6246.     fmov.x        %fp0,X(%a6)
  6247.     and.l        &0x7FFFFFFF,%d1
  6248.  
  6249.     cmp.l        %d1,&0x3FFB8000        # |X| >= 1/16?
  6250.     bge.b        ATANOK1
  6251.     bra.w        ATANSM
  6252.  
  6253. ATANOK1:
  6254.     cmp.l        %d1,&0x4002FFFF        # |X| < 16 ?
  6255.     ble.b        ATANMAIN
  6256.     bra.w        ATANBIG
  6257.  
  6258. #--THE MOST LIKELY CASE, |X| IN [1/16, 16). WE USE TABLE TECHNIQUE
  6259. #--THE IDEA IS ATAN(X) = ATAN(F) + ATAN( [X-F] / [1+XF] ).
  6260. #--SO IF F IS CHOSEN TO BE CLOSE TO X AND ATAN(F) IS STORED IN
  6261. #--A TABLE, ALL WE NEED IS TO APPROXIMATE ATAN(U) WHERE
  6262. #--U = (X-F)/(1+XF) IS SMALL (REMEMBER F IS CLOSE TO X). IT IS
  6263. #--TRUE THAT A DIVIDE IS NOW NEEDED, BUT THE APPROXIMATION FOR
  6264. #--ATAN(U) IS A VERY SHORT POLYNOMIAL AND THE INDEXING TO
  6265. #--FETCH F AND SAVING OF REGISTERS CAN BE ALL HIDED UNDER THE
  6266. #--DIVIDE. IN THE END THIS METHOD IS MUCH FASTER THAN A TRADITIONAL
  6267. #--ONE. NOTE ALSO THAT THE TRADITIONAL SCHEME THAT APPROXIMATE
  6268. #--ATAN(X) DIRECTLY WILL NEED TO USE A RATIONAL APPROXIMATION
  6269. #--(DIVISION NEEDED) ANYWAY BECAUSE A POLYNOMIAL APPROXIMATION
  6270. #--WILL INVOLVE A VERY LONG POLYNOMIAL.
  6271.  
  6272. #--NOW WE SEE X AS +-2^K * 1.BBBBBBB....B <- 1. + 63 BITS
  6273. #--WE CHOSE F TO BE +-2^K * 1.BBBB1
  6274. #--THAT IS IT MATCHES THE EXPONENT AND FIRST 5 BITS OF X, THE
  6275. #--SIXTH BITS IS SET TO BE 1. SINCE K = -4, -3, ..., 3, THERE
  6276. #--ARE ONLY 8 TIMES 16 = 2^7 = 128 |F|'S. SINCE ATAN(-|F|) IS
  6277. #-- -ATAN(|F|), WE NEED TO STORE ONLY ATAN(|F|).
  6278.  
  6279. ATANMAIN:
  6280.  
  6281.     and.l        &0xF8000000,XFRAC(%a6)    # FIRST 5 BITS
  6282.     or.l        &0x04000000,XFRAC(%a6)    # SET 6-TH BIT TO 1
  6283.     mov.l        &0x00000000,XFRACLO(%a6) # LOCATION OF X IS NOW F
  6284.  
  6285.     fmov.x        %fp0,%fp1        # FP1 IS X
  6286.     fmul.x        X(%a6),%fp1        # FP1 IS X*F, NOTE THAT X*F > 0
  6287.     fsub.x        X(%a6),%fp0        # FP0 IS X-F
  6288.     fadd.s        &0x3F800000,%fp1    # FP1 IS 1 + X*F
  6289.     fdiv.x        %fp1,%fp0        # FP0 IS U = (X-F)/(1+X*F)
  6290.  
  6291. #--WHILE THE DIVISION IS TAKING ITS TIME, WE FETCH ATAN(|F|)
  6292. #--CREATE ATAN(F) AND STORE IT IN ATANF, AND
  6293. #--SAVE REGISTERS FP2.
  6294.  
  6295.     mov.l        %d2,-(%sp)        # SAVE d2 TEMPORARILY
  6296.     mov.l        %d1,%d2            # THE EXP AND 16 BITS OF X
  6297.     and.l        &0x00007800,%d1        # 4 VARYING BITS OF F'S FRACTION
  6298.     and.l        &0x7FFF0000,%d2        # EXPONENT OF F
  6299.     sub.l        &0x3FFB0000,%d2        # K+4
  6300.     asr.l        &1,%d2
  6301.     add.l        %d2,%d1            # THE 7 BITS IDENTIFYING F
  6302.     asr.l        &7,%d1            # INDEX INTO TBL OF ATAN(|F|)
  6303.     lea        ATANTBL(%pc),%a1
  6304.     add.l        %d1,%a1            # ADDRESS OF ATAN(|F|)
  6305.     mov.l        (%a1)+,ATANF(%a6)
  6306.     mov.l        (%a1)+,ATANFHI(%a6)
  6307.     mov.l        (%a1)+,ATANFLO(%a6)    # ATANF IS NOW ATAN(|F|)
  6308.     mov.l        X(%a6),%d1        # LOAD SIGN AND EXPO. AGAIN
  6309.     and.l        &0x80000000,%d1        # SIGN(F)
  6310.     or.l        %d1,ATANF(%a6)        # ATANF IS NOW SIGN(F)*ATAN(|F|)
  6311.     mov.l        (%sp)+,%d2        # RESTORE d2
  6312.  
  6313. #--THAT'S ALL I HAVE TO DO FOR NOW,
  6314. #--BUT ALAS, THE DIVIDE IS STILL CRANKING!
  6315.  
  6316. #--U IN FP0, WE ARE NOW READY TO COMPUTE ATAN(U) AS
  6317. #--U + A1*U*V*(A2 + V*(A3 + V)), V = U*U
  6318. #--THE POLYNOMIAL MAY LOOK STRANGE, BUT IS NEVERTHELESS CORRECT.
  6319. #--THE NATURAL FORM IS U + U*V*(A1 + V*(A2 + V*A3))
  6320. #--WHAT WE HAVE HERE IS MERELY    A1 = A3, A2 = A1/A3, A3 = A2/A3.
  6321. #--THE REASON FOR THIS REARRANGEMENT IS TO MAKE THE INDEPENDENT
  6322. #--PARTS A1*U*V AND (A2 + ... STUFF) MORE LOAD-BALANCED
  6323.  
  6324.     fmovm.x        &0x04,-(%sp)        # save fp2
  6325.  
  6326.     fmov.x        %fp0,%fp1
  6327.     fmul.x        %fp1,%fp1
  6328.     fmov.d        ATANA3(%pc),%fp2
  6329.     fadd.x        %fp1,%fp2        # A3+V
  6330.     fmul.x        %fp1,%fp2        # V*(A3+V)
  6331.     fmul.x        %fp0,%fp1        # U*V
  6332.     fadd.d        ATANA2(%pc),%fp2    # A2+V*(A3+V)
  6333.     fmul.d        ATANA1(%pc),%fp1    # A1*U*V
  6334.     fmul.x        %fp2,%fp1        # A1*U*V*(A2+V*(A3+V))
  6335.     fadd.x        %fp1,%fp0        # ATAN(U), FP1 RELEASED
  6336.  
  6337.     fmovm.x     (%sp)+,&0x20        # restore fp2
  6338.  
  6339.     fmov.l        %d0,%fpcr        # restore users rnd mode,prec
  6340.     fadd.x        ATANF(%a6),%fp0        # ATAN(X)
  6341.     bra        t_inx2
  6342.  
  6343. ATANBORS:
  6344. #--|X| IS IN d0 IN COMPACT FORM. FP1, d0 SAVED.
  6345. #--FP0 IS X AND |X| <= 1/16 OR |X| >= 16.
  6346.     cmp.l        %d1,&0x3FFF8000
  6347.     bgt.w        ATANBIG            # I.E. |X| >= 16
  6348.  
  6349. ATANSM:
  6350. #--|X| <= 1/16
  6351. #--IF |X| < 2^(-40), RETURN X AS ANSWER. OTHERWISE, APPROXIMATE
  6352. #--ATAN(X) BY X + X*Y*(B1+Y*(B2+Y*(B3+Y*(B4+Y*(B5+Y*B6)))))
  6353. #--WHICH IS X + X*Y*( [B1+Z*(B3+Z*B5)] + [Y*(B2+Z*(B4+Z*B6)] )
  6354. #--WHERE Y = X*X, AND Z = Y*Y.
  6355.  
  6356.     cmp.l        %d1,&0x3FD78000
  6357.     blt.w        ATANTINY
  6358.  
  6359. #--COMPUTE POLYNOMIAL
  6360.     fmovm.x        &0x0c,-(%sp)        # save fp2/fp3
  6361.  
  6362.     fmul.x        %fp0,%fp0        # FPO IS Y = X*X
  6363.  
  6364.     fmov.x        %fp0,%fp1
  6365.     fmul.x        %fp1,%fp1        # FP1 IS Z = Y*Y
  6366.  
  6367.     fmov.d        ATANB6(%pc),%fp2
  6368.     fmov.d        ATANB5(%pc),%fp3
  6369.  
  6370.     fmul.x        %fp1,%fp2        # Z*B6
  6371.     fmul.x        %fp1,%fp3        # Z*B5
  6372.  
  6373.     fadd.d        ATANB4(%pc),%fp2    # B4+Z*B6
  6374.     fadd.d        ATANB3(%pc),%fp3    # B3+Z*B5
  6375.  
  6376.     fmul.x        %fp1,%fp2        # Z*(B4+Z*B6)
  6377.     fmul.x        %fp3,%fp1        # Z*(B3+Z*B5)
  6378.  
  6379.     fadd.d        ATANB2(%pc),%fp2    # B2+Z*(B4+Z*B6)
  6380.     fadd.d        ATANB1(%pc),%fp1    # B1+Z*(B3+Z*B5)
  6381.  
  6382.     fmul.x        %fp0,%fp2        # Y*(B2+Z*(B4+Z*B6))
  6383.     fmul.x        X(%a6),%fp0        # X*Y
  6384.  
  6385.     fadd.x        %fp2,%fp1        # [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]
  6386.  
  6387.     fmul.x        %fp1,%fp0        # X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))])
  6388.  
  6389.     fmovm.x        (%sp)+,&0x30        # restore fp2/fp3
  6390.  
  6391.     fmov.l        %d0,%fpcr        # restore users rnd mode,prec
  6392.     fadd.x        X(%a6),%fp0
  6393.     bra        t_inx2
  6394.  
  6395. ATANTINY:
  6396. #--|X| < 2^(-40), ATAN(X) = X
  6397.  
  6398.     fmov.l        %d0,%fpcr        # restore users rnd mode,prec
  6399.     mov.b        &FMOV_OP,%d1        # last inst is MOVE
  6400.     fmov.x        X(%a6),%fp0        # last inst - possible exception set
  6401.  
  6402.     bra        t_catch
  6403.  
  6404. ATANBIG:
  6405. #--IF |X| > 2^(100), RETURN    SIGN(X)*(PI/2 - TINY). OTHERWISE,
  6406. #--RETURN SIGN(X)*PI/2 + ATAN(-1/X).
  6407.     cmp.l        %d1,&0x40638000
  6408.     bgt.w        ATANHUGE
  6409.  
  6410. #--APPROXIMATE ATAN(-1/X) BY
  6411. #--X'+X'*Y*(C1+Y*(C2+Y*(C3+Y*(C4+Y*C5)))), X' = -1/X, Y = X'*X'
  6412. #--THIS CAN BE RE-WRITTEN AS
  6413. #--X'+X'*Y*( [C1+Z*(C3+Z*C5)] + [Y*(C2+Z*C4)] ), Z = Y*Y.
  6414.  
  6415.     fmovm.x        &0x0c,-(%sp)        # save fp2/fp3
  6416.  
  6417.     fmov.s        &0xBF800000,%fp1    # LOAD -1
  6418.     fdiv.x        %fp0,%fp1        # FP1 IS -1/X
  6419.  
  6420. #--DIVIDE IS STILL CRANKING
  6421.  
  6422.     fmov.x        %fp1,%fp0        # FP0 IS X'
  6423.     fmul.x        %fp0,%fp0        # FP0 IS Y = X'*X'
  6424.     fmov.x        %fp1,X(%a6)        # X IS REALLY X'
  6425.  
  6426.     fmov.x        %fp0,%fp1
  6427.     fmul.x        %fp1,%fp1        # FP1 IS Z = Y*Y
  6428.  
  6429.     fmov.d        ATANC5(%pc),%fp3
  6430.     fmov.d        ATANC4(%pc),%fp2
  6431.  
  6432.     fmul.x        %fp1,%fp3        # Z*C5
  6433.     fmul.x        %fp1,%fp2        # Z*B4
  6434.  
  6435.     fadd.d        ATANC3(%pc),%fp3    # C3+Z*C5
  6436.     fadd.d        ATANC2(%pc),%fp2    # C2+Z*C4
  6437.  
  6438.     fmul.x        %fp3,%fp1        # Z*(C3+Z*C5), FP3 RELEASED
  6439.     fmul.x        %fp0,%fp2        # Y*(C2+Z*C4)
  6440.  
  6441.     fadd.d        ATANC1(%pc),%fp1    # C1+Z*(C3+Z*C5)
  6442.     fmul.x        X(%a6),%fp0        # X'*Y
  6443.  
  6444.     fadd.x        %fp2,%fp1        # [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)]
  6445.  
  6446.     fmul.x        %fp1,%fp0        # X'*Y*([B1+Z*(B3+Z*B5)]
  6447. #                    ...    +[Y*(B2+Z*(B4+Z*B6))])
  6448.     fadd.x        X(%a6),%fp0
  6449.  
  6450.     fmovm.x        (%sp)+,&0x30        # restore fp2/fp3
  6451.  
  6452.     fmov.l        %d0,%fpcr        # restore users rnd mode,prec
  6453.     tst.b        (%a0)
  6454.     bpl.b        pos_big
  6455.  
  6456. neg_big:
  6457.     fadd.x        NPIBY2(%pc),%fp0
  6458.     bra        t_minx2
  6459.  
  6460. pos_big:
  6461.     fadd.x        PPIBY2(%pc),%fp0
  6462.     bra        t_pinx2
  6463.  
  6464. ATANHUGE:
  6465. #--RETURN SIGN(X)*(PIBY2 - TINY) = SIGN(X)*PIBY2 - SIGN(X)*TINY
  6466.     tst.b        (%a0)
  6467.     bpl.b        pos_huge
  6468.  
  6469. neg_huge:
  6470.     fmov.x        NPIBY2(%pc),%fp0
  6471.     fmov.l        %d0,%fpcr
  6472.     fadd.x        PTINY(%pc),%fp0
  6473.     bra        t_minx2
  6474.  
  6475. pos_huge:
  6476.     fmov.x        PPIBY2(%pc),%fp0
  6477.     fmov.l        %d0,%fpcr
  6478.     fadd.x        NTINY(%pc),%fp0
  6479.     bra        t_pinx2
  6480.  
  6481.     global        satand
  6482. #--ENTRY POINT FOR ATAN(X) FOR DENORMALIZED ARGUMENT
  6483. satand:
  6484.     bra        t_extdnrm
  6485.  
  6486. #########################################################################
  6487. # sasin():  computes the inverse sine of a normalized input        #
  6488. # sasind(): computes the inverse sine of a denormalized input        #
  6489. #                                    #
  6490. # INPUT ***************************************************************    #
  6491. #    a0 = pointer to extended precision input            #
  6492. #    d0 = round precision,mode                    #
  6493. #                                    #
  6494. # OUTPUT **************************************************************    # 
  6495. #    fp0 = arcsin(X)                            #
  6496. #                                    #
  6497. # ACCURACY and MONOTONICITY *******************************************    #
  6498. #    The returned result is within 3 ulps in    64 significant bit,    #
  6499. #    i.e. within 0.5001 ulp to 53 bits if the result is subsequently    #
  6500. #    rounded to double precision. The result is provably monotonic    #
  6501. #    in double precision.                        #
  6502. #                                    #
  6503. # ALGORITHM ***********************************************************    #
  6504. #                                    #
  6505. #    ASIN                                #
  6506. #    1. If |X| >= 1, go to 3.                    #
  6507. #                                    #
  6508. #    2. (|X| < 1) Calculate asin(X) by                #
  6509. #        z := sqrt( [1-X][1+X] )                    #
  6510. #        asin(X) = atan( x / z ).                #
  6511. #        Exit.                            #
  6512. #                                    #
  6513. #    3. If |X| > 1, go to 5.                        #
  6514. #                                    #
  6515. #    4. (|X| = 1) sgn := sign(X), return asin(X) := sgn * Pi/2. Exit.#
  6516. #                                    #
  6517. #    5. (|X| > 1) Generate an invalid operation by 0 * infinity.    #
  6518. #        Exit.                            #
  6519. #                                    #
  6520. #########################################################################
  6521.  
  6522.     global        sasin
  6523. sasin:
  6524.     fmov.x        (%a0),%fp0        # LOAD INPUT
  6525.  
  6526.     mov.l        (%a0),%d1
  6527.     mov.w        4(%a0),%d1
  6528.     and.l        &0x7FFFFFFF,%d1
  6529.     cmp.l        %d1,&0x3FFF8000
  6530.     bge.b        ASINBIG
  6531.  
  6532. # This catch is added here for the '060 QSP. Originally, the call to
  6533. # satan() would handle this case by causing the exception which would
  6534. # not be caught until gen_except(). Now, with the exceptions being 
  6535. # detected inside of satan(), the exception would have been handled there
  6536. # instead of inside sasin() as expected.
  6537.     cmp.l        %d1,&0x3FD78000
  6538.     blt.w        ASINTINY
  6539.  
  6540. #--THIS IS THE USUAL CASE, |X| < 1
  6541. #--ASIN(X) = ATAN( X / SQRT( (1-X)(1+X) ) )
  6542.  
  6543. ASINMAIN:
  6544.     fmov.s        &0x3F800000,%fp1
  6545.     fsub.x        %fp0,%fp1        # 1-X
  6546.     fmovm.x        &0x4,-(%sp)        #  {fp2}
  6547.     fmov.s        &0x3F800000,%fp2
  6548.     fadd.x        %fp0,%fp2        # 1+X
  6549.     fmul.x        %fp2,%fp1        # (1+X)(1-X)
  6550.     fmovm.x        (%sp)+,&0x20        #  {fp2}
  6551.     fsqrt.x        %fp1            # SQRT([1-X][1+X])
  6552.     fdiv.x        %fp1,%fp0        # X/SQRT([1-X][1+X])
  6553.     fmovm.x        &0x01,-(%sp)        # save X/SQRT(...)
  6554.     lea        (%sp),%a0        # pass ptr to X/SQRT(...)
  6555.     bsr        satan
  6556.     add.l        &0xc,%sp        # clear X/SQRT(...) from stack
  6557.     bra        t_inx2
  6558.  
  6559. ASINBIG:
  6560.     fabs.x        %fp0            # |X|
  6561.     fcmp.s        %fp0,&0x3F800000
  6562.     fbgt        t_operr            # cause an operr exception
  6563.  
  6564. #--|X| = 1, ASIN(X) = +- PI/2.
  6565. ASINONE:
  6566.     fmov.x        PIBY2(%pc),%fp0
  6567.     mov.l        (%a0),%d1
  6568.     and.l        &0x80000000,%d1        # SIGN BIT OF X
  6569.     or.l        &0x3F800000,%d1        # +-1 IN SGL FORMAT
  6570.     mov.l        %d1,-(%sp)        # push SIGN(X) IN SGL-FMT
  6571.     fmov.l        %d0,%fpcr
  6572.     fmul.s        (%sp)+,%fp0
  6573.     bra        t_inx2
  6574.  
  6575. #--|X| < 2^(-40), ATAN(X) = X
  6576. ASINTINY:
  6577.     fmov.l        %d0,%fpcr        # restore users rnd mode,prec
  6578.     mov.b        &FMOV_OP,%d1        # last inst is MOVE
  6579.     fmov.x        (%a0),%fp0        # last inst - possible exception
  6580.     bra        t_catch
  6581.  
  6582.     global        sasind
  6583. #--ASIN(X) = X FOR DENORMALIZED X
  6584. sasind:
  6585.     bra        t_extdnrm
  6586.  
  6587. #########################################################################
  6588. # sacos():  computes the inverse cosine of a normalized input        #
  6589. # sacosd(): computes the inverse cosine of a denormalized input        #
  6590. #                                    #
  6591. # INPUT ***************************************************************    #
  6592. #    a0 = pointer to extended precision input            #
  6593. #    d0 = round precision,mode                    #
  6594. #                                    #
  6595. # OUTPUT ************************************************************** #
  6596. #    fp0 = arccos(X)                            #
  6597. #                                    #
  6598. # ACCURACY and MONOTONICITY *******************************************    #
  6599. #    The returned result is within 3 ulps in    64 significant bit,    #
  6600. #    i.e. within 0.5001 ulp to 53 bits if the result is subsequently    #
  6601. #    rounded to double precision. The result is provably monotonic    #
  6602. #    in double precision.                        #
  6603. #                                    #
  6604. # ALGORITHM *********************************************************** #
  6605. #                                    #
  6606. #    ACOS                                #
  6607. #    1. If |X| >= 1, go to 3.                    #
  6608. #                                    #
  6609. #    2. (|X| < 1) Calculate acos(X) by                #
  6610. #        z := (1-X) / (1+X)                    #
  6611. #        acos(X) = 2 * atan( sqrt(z) ).                #
  6612. #        Exit.                            #
  6613. #                                    #
  6614. #    3. If |X| > 1, go to 5.                        #
  6615. #                                    #
  6616. #    4. (|X| = 1) If X > 0, return 0. Otherwise, return Pi. Exit.    #
  6617. #                                    #
  6618. #    5. (|X| > 1) Generate an invalid operation by 0 * infinity.    #
  6619. #        Exit.                            #
  6620. #                                    #
  6621. #########################################################################
  6622.  
  6623.     global        sacos
  6624. sacos:
  6625.     fmov.x        (%a0),%fp0        # LOAD INPUT
  6626.  
  6627.     mov.l        (%a0),%d1        # pack exp w/ upper 16 fraction
  6628.     mov.w        4(%a0),%d1
  6629.     and.l        &0x7FFFFFFF,%d1
  6630.     cmp.l        %d1,&0x3FFF8000
  6631.     bge.b        ACOSBIG
  6632.  
  6633. #--THIS IS THE USUAL CASE, |X| < 1
  6634. #--ACOS(X) = 2 * ATAN(    SQRT( (1-X)/(1+X) ) )
  6635.  
  6636. ACOSMAIN:
  6637.     fmov.s        &0x3F800000,%fp1
  6638.     fadd.x        %fp0,%fp1        # 1+X
  6639.     fneg.x        %fp0            # -X
  6640.     fadd.s        &0x3F800000,%fp0    # 1-X
  6641.     fdiv.x        %fp1,%fp0        # (1-X)/(1+X)
  6642.     fsqrt.x        %fp0            # SQRT((1-X)/(1+X))
  6643.     mov.l        %d0,-(%sp)        # save original users fpcr
  6644.     clr.l        %d0
  6645.     fmovm.x        &0x01,-(%sp)        # save SQRT(...) to stack
  6646.     lea        (%sp),%a0        # pass ptr to sqrt
  6647.     bsr        satan            # ATAN(SQRT([1-X]/[1+X]))
  6648.     add.l        &0xc,%sp        # clear SQRT(...) from stack
  6649.  
  6650.     fmov.l        (%sp)+,%fpcr        # restore users round prec,mode
  6651.     fadd.x        %fp0,%fp0        # 2 * ATAN( STUFF )
  6652.     bra        t_pinx2
  6653.  
  6654. ACOSBIG:
  6655.     fabs.x        %fp0
  6656.     fcmp.s        %fp0,&0x3F800000
  6657.     fbgt        t_operr            # cause an operr exception
  6658.  
  6659. #--|X| = 1, ACOS(X) = 0 OR PI
  6660.     tst.b        (%a0)            # is X positive or negative?
  6661.     bpl.b        ACOSP1
  6662.  
  6663. #--X = -1
  6664. #Returns PI and inexact exception
  6665. ACOSM1:
  6666.     fmov.x        PI(%pc),%fp0        # load PI
  6667.     fmov.l        %d0,%fpcr        # load round mode,prec
  6668.     fadd.s        &0x00800000,%fp0    # add a small value
  6669.     bra        t_pinx2
  6670.  
  6671. ACOSP1:
  6672.     bra        ld_pzero        # answer is positive zero
  6673.  
  6674.     global        sacosd
  6675. #--ACOS(X) = PI/2 FOR DENORMALIZED X
  6676. sacosd:
  6677.     fmov.l        %d0,%fpcr        # load user's rnd mode/prec
  6678.     fmov.x        PIBY2(%pc),%fp0
  6679.     bra        t_pinx2
  6680.  
  6681. #########################################################################
  6682. # setox():    computes the exponential for a normalized input        #
  6683. # setoxd():   computes the exponential for a denormalized input        # 
  6684. # setoxm1():  computes the exponential minus 1 for a normalized input    #
  6685. # setoxm1d(): computes the exponential minus 1 for a denormalized input    #
  6686. #                                    #
  6687. # INPUT    *************************************************************** #
  6688. #    a0 = pointer to extended precision input            #
  6689. #    d0 = round precision,mode                    #
  6690. #                                    #
  6691. # OUTPUT ************************************************************** #
  6692. #    fp0 = exp(X) or exp(X)-1                    #
  6693. #                                    #
  6694. # ACCURACY and MONOTONICITY ******************************************* #
  6695. #    The returned result is within 0.85 ulps in 64 significant bit,     #
  6696. #    i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
  6697. #    rounded to double precision. The result is provably monotonic     #
  6698. #    in double precision.                        #
  6699. #                                    #
  6700. # ALGORITHM and IMPLEMENTATION **************************************** #
  6701. #                                    #
  6702. #    setoxd                                #
  6703. #    ------                                #
  6704. #    Step 1.    Set ans := 1.0                        #
  6705. #                                    #
  6706. #    Step 2.    Return    ans := ans + sign(X)*2^(-126). Exit.        #
  6707. #    Notes:    This will always generate one exception -- inexact.    #
  6708. #                                    #
  6709. #                                    #
  6710. #    setox                                #
  6711. #    -----                                #
  6712. #                                    #
  6713. #    Step 1.    Filter out extreme cases of input argument.        #
  6714. #        1.1    If |X| >= 2^(-65), go to Step 1.3.        #
  6715. #        1.2    Go to Step 7.                    #
  6716. #        1.3    If |X| < 16380 log(2), go to Step 2.        #
  6717. #        1.4    Go to Step 8.                    #
  6718. #    Notes:    The usual case should take the branches 1.1 -> 1.3 -> 2.#
  6719. #        To avoid the use of floating-point comparisons, a    #
  6720. #        compact representation of |X| is used. This format is a    #
  6721. #        32-bit integer, the upper (more significant) 16 bits     #
  6722. #        are the sign and biased exponent field of |X|; the     #
  6723. #        lower 16 bits are the 16 most significant fraction    #
  6724. #        (including the explicit bit) bits of |X|. Consequently,    #
  6725. #        the comparisons in Steps 1.1 and 1.3 can be performed    #
  6726. #        by integer comparison. Note also that the constant    #
  6727. #        16380 log(2) used in Step 1.3 is also in the compact    #
  6728. #        form. Thus taking the branch to Step 2 guarantees     #
  6729. #        |X| < 16380 log(2). There is no harm to have a small    #
  6730. #        number of cases where |X| is less than,    but close to,    #
  6731. #        16380 log(2) and the branch to Step 9 is taken.        #
  6732. #                                    #
  6733. #    Step 2.    Calculate N = round-to-nearest-int( X * 64/log2 ).    #
  6734. #        2.1    Set AdjFlag := 0 (indicates the branch 1.3 -> 2 #
  6735. #            was taken)                    #
  6736. #        2.2    N := round-to-nearest-integer( X * 64/log2 ).    #
  6737. #        2.3    Calculate    J = N mod 64; so J = 0,1,2,..., #
  6738. #            or 63.                        #
  6739. #        2.4    Calculate    M = (N - J)/64; so N = 64M + J.    #
  6740. #        2.5    Calculate the address of the stored value of     #
  6741. #            2^(J/64).                    #
  6742. #        2.6    Create the value Scale = 2^M.            #
  6743. #    Notes:    The calculation in 2.2 is really performed by        #
  6744. #            Z := X * constant                #
  6745. #            N := round-to-nearest-integer(Z)        #
  6746. #        where                            #
  6747. #            constant := single-precision( 64/log 2 ).    #
  6748. #                                    #
  6749. #        Using a single-precision constant avoids memory     #
  6750. #        access. Another effect of using a single-precision    #
  6751. #        "constant" is that the calculated value Z is         #
  6752. #                                    #
  6753. #            Z = X*(64/log2)*(1+eps), |eps| <= 2^(-24).    #
  6754. #                                    #
  6755. #        This error has to be considered later in Steps 3 and 4.    #
  6756. #                                    #
  6757. #    Step 3.    Calculate X - N*log2/64.                #
  6758. #        3.1    R := X + N*L1,                     #
  6759. #                where L1 := single-precision(-log2/64).    #
  6760. #        3.2    R := R + N*L2,                     #
  6761. #                L2 := extended-precision(-log2/64 - L1).#
  6762. #    Notes:    a) The way L1 and L2 are chosen ensures L1+L2         #
  6763. #        approximate the value -log2/64 to 88 bits of accuracy.    #
  6764. #        b) N*L1 is exact because N is no longer than 22 bits    #
  6765. #        and L1 is no longer than 24 bits.            #
  6766. #        c) The calculation X+N*L1 is also exact due to         #
  6767. #        cancellation. Thus, R is practically X+N(L1+L2) to full    #
  6768. #        64 bits.                         #
  6769. #        d) It is important to estimate how large can |R| be    #
  6770. #        after Step 3.2.                        #
  6771. #                                    #
  6772. #        N = rnd-to-int( X*64/log2 (1+eps) ), |eps|<=2^(-24)    #
  6773. #        X*64/log2 (1+eps)    =    N + f,    |f| <= 0.5    #
  6774. #        X*64/log2 - N    =    f - eps*X 64/log2        #
  6775. #        X - N*log2/64    =    f*log2/64 - eps*X        #
  6776. #                                    #
  6777. #                                    #
  6778. #        Now |X| <= 16446 log2, thus                #
  6779. #                                    #
  6780. #            |X - N*log2/64| <= (0.5 + 16446/2^(18))*log2/64    #
  6781. #                    <= 0.57 log2/64.        #
  6782. #         This bound will be used in Step 4.            #
  6783. #                                    #
  6784. #    Step 4.    Approximate exp(R)-1 by a polynomial            #
  6785. #        p = R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))    #
  6786. #    Notes:    a) In order to reduce memory access, the coefficients     #
  6787. #        are made as "short" as possible: A1 (which is 1/2), A4    #
  6788. #        and A5 are single precision; A2 and A3 are double    #
  6789. #        precision.                         #
  6790. #        b) Even with the restrictions above,             #
  6791. #           |p - (exp(R)-1)| < 2^(-68.8) for all |R| <= 0.0062.    #
  6792. #        Note that 0.0062 is slightly bigger than 0.57 log2/64.    #
  6793. #        c) To fully utilize the pipeline, p is separated into    #
  6794. #        two independent pieces of roughly equal complexities    #
  6795. #            p = [ R + R*S*(A2 + S*A4) ]    +        #
  6796. #                [ S*(A1 + S*(A3 + S*A5)) ]        #
  6797. #        where S = R*R.                        #
  6798. #                                    #
  6799. #    Step 5.    Compute 2^(J/64)*exp(R) = 2^(J/64)*(1+p) by        #
  6800. #                ans := T + ( T*p + t)            #
  6801. #        where T and t are the stored values for 2^(J/64).    #
  6802. #    Notes:    2^(J/64) is stored as T and t where T+t approximates    #
  6803. #        2^(J/64) to roughly 85 bits; T is in extended precision    #
  6804. #        and t is in single precision. Note also that T is     #
  6805. #        rounded to 62 bits so that the last two bits of T are     #
  6806. #        zero. The reason for such a special form is that T-1,     #
  6807. #        T-2, and T-8 will all be exact --- a property that will    #
  6808. #        give much more accurate computation of the function     #
  6809. #        EXPM1.                            #
  6810. #                                    #
  6811. #    Step 6.    Reconstruction of exp(X)                #
  6812. #            exp(X) = 2^M * 2^(J/64) * exp(R).        #
  6813. #        6.1    If AdjFlag = 0, go to 6.3            #
  6814. #        6.2    ans := ans * AdjScale                #
  6815. #        6.3    Restore the user FPCR                #
  6816. #        6.4    Return ans := ans * Scale. Exit.        #
  6817. #    Notes:    If AdjFlag = 0, we have X = Mlog2 + Jlog2/64 + R,    #
  6818. #        |M| <= 16380, and Scale = 2^M. Moreover, exp(X) will    #
  6819. #        neither overflow nor underflow. If AdjFlag = 1, that    #
  6820. #        means that                        #
  6821. #            X = (M1+M)log2 + Jlog2/64 + R, |M1+M| >= 16380.    #
  6822. #        Hence, exp(X) may overflow or underflow or neither.    #
  6823. #        When that is the case, AdjScale = 2^(M1) where M1 is    #
  6824. #        approximately M. Thus 6.2 will never cause         #
  6825. #        over/underflow. Possible exception in 6.4 is overflow    #
  6826. #        or underflow. The inexact exception is not generated in    #
  6827. #        6.4. Although one can argue that the inexact flag    #
  6828. #        should always be raised, to simulate that exception     #
  6829. #        cost to much than the flag is worth in practical uses.    #
  6830. #                                    #
  6831. #    Step 7.    Return 1 + X.                        #
  6832. #        7.1    ans := X                    #
  6833. #        7.2    Restore user FPCR.                #
  6834. #        7.3    Return ans := 1 + ans. Exit            #
  6835. #    Notes:    For non-zero X, the inexact exception will always be    #
  6836. #        raised by 7.3. That is the only exception raised by 7.3.#
  6837. #        Note also that we use the FMOVEM instruction to move X    #
  6838. #        in Step 7.1 to avoid unnecessary trapping. (Although    #
  6839. #        the FMOVEM may not seem relevant since X is normalized,    #
  6840. #        the precaution will be useful in the library version of    #
  6841. #        this code where the separate entry for denormalized     #
  6842. #        inputs will be done away with.)                #
  6843. #                                    #
  6844. #    Step 8.    Handle exp(X) where |X| >= 16380log2.            #
  6845. #        8.1    If |X| > 16480 log2, go to Step 9.        #
  6846. #        (mimic 2.2 - 2.6)                    #
  6847. #        8.2    N := round-to-integer( X * 64/log2 )        #
  6848. #        8.3    Calculate J = N mod 64, J = 0,1,...,63        #
  6849. #        8.4    K := (N-J)/64, M1 := truncate(K/2), M = K-M1,     #
  6850. #            AdjFlag := 1.                    #
  6851. #        8.5    Calculate the address of the stored value     #
  6852. #            2^(J/64).                    #
  6853. #        8.6    Create the values Scale = 2^M, AdjScale = 2^M1.    #
  6854. #        8.7    Go to Step 3.                    #
  6855. #    Notes:    Refer to notes for 2.2 - 2.6.                #
  6856. #                                    #
  6857. #    Step 9.    Handle exp(X), |X| > 16480 log2.            #
  6858. #        9.1    If X < 0, go to 9.3                #
  6859. #        9.2    ans := Huge, go to 9.4                #
  6860. #        9.3    ans := Tiny.                    #
  6861. #        9.4    Restore user FPCR.                #
  6862. #        9.5    Return ans := ans * ans. Exit.            #
  6863. #    Notes:    Exp(X) will surely overflow or underflow, depending on    #
  6864. #        X's sign. "Huge" and "Tiny" are respectively large/tiny    #
  6865. #        extended-precision numbers whose square over/underflow    #
  6866. #        with an inexact result. Thus, 9.5 always raises the    #
  6867. #        inexact together with either overflow or underflow.    #
  6868. #                                    #
  6869. #    setoxm1d                            #
  6870. #    --------                            #
  6871. #                                    #
  6872. #    Step 1.    Set ans := 0                        #
  6873. #                                    #
  6874. #    Step 2.    Return    ans := X + ans. Exit.                #
  6875. #    Notes:    This will return X with the appropriate rounding    #
  6876. #         precision prescribed by the user FPCR.            #
  6877. #                                    #
  6878. #    setoxm1                                #
  6879. #    -------                                #
  6880. #                                    #
  6881. #    Step 1.    Check |X|                        #
  6882. #        1.1    If |X| >= 1/4, go to Step 1.3.            #
  6883. #        1.2    Go to Step 7.                    #
  6884. #        1.3    If |X| < 70 log(2), go to Step 2.        #
  6885. #        1.4    Go to Step 10.                    #
  6886. #    Notes:    The usual case should take the branches 1.1 -> 1.3 -> 2.#
  6887. #        However, it is conceivable |X| can be small very often    #
  6888. #        because EXPM1 is intended to evaluate exp(X)-1         #
  6889. #        accurately when |X| is small. For further details on     #
  6890. #        the comparisons, see the notes on Step 1 of setox.    #
  6891. #                                    #
  6892. #    Step 2.    Calculate N = round-to-nearest-int( X * 64/log2 ).    #
  6893. #        2.1    N := round-to-nearest-integer( X * 64/log2 ).    #
  6894. #        2.2    Calculate    J = N mod 64; so J = 0,1,2,..., #
  6895. #            or 63.                        #
  6896. #        2.3    Calculate    M = (N - J)/64; so N = 64M + J.    #
  6897. #        2.4    Calculate the address of the stored value of     #
  6898. #            2^(J/64).                    #
  6899. #        2.5    Create the values Sc = 2^M and             #
  6900. #            OnebySc := -2^(-M).                #
  6901. #    Notes:    See the notes on Step 2 of setox.            #
  6902. #                                    #
  6903. #    Step 3.    Calculate X - N*log2/64.                #
  6904. #        3.1    R := X + N*L1,                     #
  6905. #                where L1 := single-precision(-log2/64).    #
  6906. #        3.2    R := R + N*L2,                     #
  6907. #                L2 := extended-precision(-log2/64 - L1).#
  6908. #    Notes:    Applying the analysis of Step 3 of setox in this case    #
  6909. #        shows that |R| <= 0.0055 (note that |X| <= 70 log2 in    #
  6910. #        this case).                        #
  6911. #                                    #
  6912. #    Step 4.    Approximate exp(R)-1 by a polynomial            #
  6913. #            p = R+R*R*(A1+R*(A2+R*(A3+R*(A4+R*(A5+R*A6)))))    #
  6914. #    Notes:    a) In order to reduce memory access, the coefficients     #
  6915. #        are made as "short" as possible: A1 (which is 1/2), A5     #
  6916. #        and A6 are single precision; A2, A3 and A4 are double     #
  6917. #        precision.                         #
  6918. #        b) Even with the restriction above,            #
  6919. #            |p - (exp(R)-1)| <    |R| * 2^(-72.7)        #
  6920. #        for all |R| <= 0.0055.                    #
  6921. #        c) To fully utilize the pipeline, p is separated into    #
  6922. #        two independent pieces of roughly equal complexity    #
  6923. #            p = [ R*S*(A2 + S*(A4 + S*A6)) ]    +    #
  6924. #                [ R + S*(A1 + S*(A3 + S*A5)) ]        #
  6925. #        where S = R*R.                        #
  6926. #                                    #
  6927. #    Step 5.    Compute 2^(J/64)*p by                    #
  6928. #                p := T*p                #
  6929. #        where T and t are the stored values for 2^(J/64).    #
  6930. #    Notes:    2^(J/64) is stored as T and t where T+t approximates    #
  6931. #        2^(J/64) to roughly 85 bits; T is in extended precision    #
  6932. #        and t is in single precision. Note also that T is     #
  6933. #        rounded to 62 bits so that the last two bits of T are     #
  6934. #        zero. The reason for such a special form is that T-1,     #
  6935. #        T-2, and T-8 will all be exact --- a property that will    #
  6936. #        be exploited in Step 6 below. The total relative error    #
  6937. #        in p is no bigger than 2^(-67.7) compared to the final    #
  6938. #        result.                            #
  6939. #                                    #
  6940. #    Step 6.    Reconstruction of exp(X)-1                #
  6941. #            exp(X)-1 = 2^M * ( 2^(J/64) + p - 2^(-M) ).    #
  6942. #        6.1    If M <= 63, go to Step 6.3.            #
  6943. #        6.2    ans := T + (p + (t + OnebySc)). Go to 6.6    #
  6944. #        6.3    If M >= -3, go to 6.5.                #
  6945. #        6.4    ans := (T + (p + t)) + OnebySc. Go to 6.6    #
  6946. #        6.5    ans := (T + OnebySc) + (p + t).            #
  6947. #        6.6    Restore user FPCR.                #
  6948. #        6.7    Return ans := Sc * ans. Exit.            #
  6949. #    Notes:    The various arrangements of the expressions give     #
  6950. #        accurate evaluations.                    #
  6951. #                                    #
  6952. #    Step 7.    exp(X)-1 for |X| < 1/4.                    #
  6953. #        7.1    If |X| >= 2^(-65), go to Step 9.        #
  6954. #        7.2    Go to Step 8.                    #
  6955. #                                    #
  6956. #    Step 8.    Calculate exp(X)-1, |X| < 2^(-65).            #
  6957. #        8.1    If |X| < 2^(-16312), goto 8.3            #
  6958. #        8.2    Restore FPCR; return ans := X - 2^(-16382).    #
  6959. #            Exit.                        #
  6960. #        8.3    X := X * 2^(140).                #
  6961. #        8.4    Restore FPCR; ans := ans - 2^(-16382).        #
  6962. #         Return ans := ans*2^(140). Exit            #
  6963. #    Notes:    The idea is to return "X - tiny" under the user        #
  6964. #        precision and rounding modes. To avoid unnecessary    #
  6965. #        inefficiency, we stay away from denormalized numbers     #
  6966. #        the best we can. For |X| >= 2^(-16312), the         #
  6967. #        straightforward 8.2 generates the inexact exception as    #
  6968. #        the case warrants.                    #
  6969. #                                    #
  6970. #    Step 9.    Calculate exp(X)-1, |X| < 1/4, by a polynomial        #
  6971. #            p = X + X*X*(B1 + X*(B2 + ... + X*B12))        #
  6972. #    Notes:    a) In order to reduce memory access, the coefficients    #
  6973. #        are made as "short" as possible: B1 (which is 1/2), B9    #
  6974. #        to B12 are single precision; B3 to B8 are double     #
  6975. #        precision; and B2 is double extended.            #
  6976. #        b) Even with the restriction above,            #
  6977. #            |p - (exp(X)-1)| < |X| 2^(-70.6)        #
  6978. #        for all |X| <= 0.251.                    #
  6979. #        Note that 0.251 is slightly bigger than 1/4.        #
  6980. #        c) To fully preserve accuracy, the polynomial is     #
  6981. #        computed as                        #
  6982. #            X + ( S*B1 +    Q ) where S = X*X and        #
  6983. #            Q    =    X*S*(B2 + X*(B3 + ... + X*B12))    #
  6984. #        d) To fully utilize the pipeline, Q is separated into    #
  6985. #        two independent pieces of roughly equal complexity    #
  6986. #            Q = [ X*S*(B2 + S*(B4 + ... + S*B12)) ] +    #
  6987. #                [ S*S*(B3 + S*(B5 + ... + S*B11)) ]    #
  6988. #                                    #
  6989. #    Step 10. Calculate exp(X)-1 for |X| >= 70 log 2.        #
  6990. #        10.1 If X >= 70log2 , exp(X) - 1 = exp(X) for all     #
  6991. #        practical purposes. Therefore, go to Step 1 of setox.    #
  6992. #        10.2 If X <= -70log2, exp(X) - 1 = -1 for all practical    #
  6993. #        purposes.                         #
  6994. #        ans := -1                         #
  6995. #        Restore user FPCR                    #
  6996. #        Return ans := ans + 2^(-126). Exit.            #
  6997. #    Notes:    10.2 will always create an inexact and return -1 + tiny    #
  6998. #        in the user rounding precision and mode.        #
  6999. #                                    #
  7000. #########################################################################
  7001.  
  7002. L2:    long        0x3FDC0000,0x82E30865,0x4361C4C6,0x00000000
  7003.  
  7004. EEXPA3:    long        0x3FA55555,0x55554CC1
  7005. EEXPA2:    long        0x3FC55555,0x55554A54
  7006.  
  7007. EM1A4:    long        0x3F811111,0x11174385
  7008. EM1A3:    long        0x3FA55555,0x55554F5A
  7009.  
  7010. EM1A2:    long        0x3FC55555,0x55555555,0x00000000,0x00000000
  7011.  
  7012. EM1B8:    long        0x3EC71DE3,0xA5774682
  7013. EM1B7:    long        0x3EFA01A0,0x19D7CB68
  7014.  
  7015. EM1B6:    long        0x3F2A01A0,0x1A019DF3
  7016. EM1B5:    long        0x3F56C16C,0x16C170E2
  7017.  
  7018. EM1B4:    long        0x3F811111,0x11111111
  7019. EM1B3:    long        0x3FA55555,0x55555555
  7020.  
  7021. EM1B2:    long        0x3FFC0000,0xAAAAAAAA,0xAAAAAAAB
  7022.     long        0x00000000
  7023.  
  7024. TWO140:    long        0x48B00000,0x00000000
  7025. TWON140:
  7026.     long        0x37300000,0x00000000
  7027.  
  7028. EEXPTBL:
  7029.     long        0x3FFF0000,0x80000000,0x00000000,0x00000000
  7030.     long        0x3FFF0000,0x8164D1F3,0xBC030774,0x9F841A9B
  7031.     long        0x3FFF0000,0x82CD8698,0xAC2BA1D8,0x9FC1D5B9
  7032.     long        0x3FFF0000,0x843A28C3,0xACDE4048,0xA0728369
  7033.     long        0x3FFF0000,0x85AAC367,0xCC487B14,0x1FC5C95C
  7034.     long        0x3FFF0000,0x871F6196,0x9E8D1010,0x1EE85C9F
  7035.     long        0x3FFF0000,0x88980E80,0x92DA8528,0x9FA20729
  7036.     long        0x3FFF0000,0x8A14D575,0x496EFD9C,0xA07BF9AF
  7037.     long        0x3FFF0000,0x8B95C1E3,0xEA8BD6E8,0xA0020DCF
  7038.     long        0x3FFF0000,0x8D1ADF5B,0x7E5BA9E4,0x205A63DA
  7039.     long        0x3FFF0000,0x8EA4398B,0x45CD53C0,0x1EB70051
  7040.     long        0x3FFF0000,0x9031DC43,0x1466B1DC,0x1F6EB029
  7041.     long        0x3FFF0000,0x91C3D373,0xAB11C338,0xA0781494
  7042.     long        0x3FFF0000,0x935A2B2F,0x13E6E92C,0x9EB319B0
  7043.     long        0x3FFF0000,0x94F4EFA8,0xFEF70960,0x2017457D
  7044.     long        0x3FFF0000,0x96942D37,0x20185A00,0x1F11D537
  7045.     long        0x3FFF0000,0x9837F051,0x8DB8A970,0x9FB952DD
  7046.     long        0x3FFF0000,0x99E04593,0x20B7FA64,0x1FE43087
  7047.     long        0x3FFF0000,0x9B8D39B9,0xD54E5538,0x1FA2A818
  7048.     long        0x3FFF0000,0x9D3ED9A7,0x2CFFB750,0x1FDE494D
  7049.     long        0x3FFF0000,0x9EF53260,0x91A111AC,0x20504890
  7050.     long        0x3FFF0000,0xA0B0510F,0xB9714FC4,0xA073691C
  7051.     long        0x3FFF0000,0xA2704303,0x0C496818,0x1F9B7A05
  7052.     long        0x3FFF0000,0xA43515AE,0x09E680A0,0xA0797126
  7053.     long        0x3FFF0000,0xA5FED6A9,0xB15138EC,0xA071A140
  7054.     long        0x3FFF0000,0xA7CD93B4,0xE9653568,0x204F62DA
  7055.     long        0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x1F283C4A
  7056.     long        0x3FFF0000,0xAB7A39B5,0xA93ED338,0x9F9A7FDC
  7057.     long        0x3FFF0000,0xAD583EEA,0x42A14AC8,0xA05B3FAC
  7058.     long        0x3FFF0000,0xAF3B78AD,0x690A4374,0x1FDF2610
  7059.     long        0x3FFF0000,0xB123F581,0xD2AC2590,0x9F705F90
  7060.     long        0x3FFF0000,0xB311C412,0xA9112488,0x201F678A
  7061.     long        0x3FFF0000,0xB504F333,0xF9DE6484,0x1F32FB13
  7062.     long        0x3FFF0000,0xB6FD91E3,0x28D17790,0x20038B30
  7063.     long        0x3FFF0000,0xB8FBAF47,0x62FB9EE8,0x200DC3CC
  7064.     long        0x3FFF0000,0xBAFF5AB2,0x133E45FC,0x9F8B2AE6
  7065.     long        0x3FFF0000,0xBD08A39F,0x580C36C0,0xA02BBF70
  7066.     long        0x3FFF0000,0xBF1799B6,0x7A731084,0xA00BF518
  7067.     long        0x3FFF0000,0xC12C4CCA,0x66709458,0xA041DD41
  7068.     long        0x3FFF0000,0xC346CCDA,0x24976408,0x9FDF137B
  7069.     long        0x3FFF0000,0xC5672A11,0x5506DADC,0x201F1568
  7070.     long        0x3FFF0000,0xC78D74C8,0xABB9B15C,0x1FC13A2E
  7071.     long        0x3FFF0000,0xC9B9BD86,0x6E2F27A4,0xA03F8F03
  7072.     long        0x3FFF0000,0xCBEC14FE,0xF2727C5C,0x1FF4907D
  7073.     long        0x3FFF0000,0xCE248C15,0x1F8480E4,0x9E6E53E4
  7074.     long        0x3FFF0000,0xD06333DA,0xEF2B2594,0x1FD6D45C
  7075.     long        0x3FFF0000,0xD2A81D91,0xF12AE45C,0xA076EDB9
  7076.     long        0x3FFF0000,0xD4F35AAB,0xCFEDFA20,0x9FA6DE21
  7077.     long        0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x1EE69A2F
  7078.     long        0x3FFF0000,0xD99D15C2,0x78AFD7B4,0x207F439F
  7079.     long        0x3FFF0000,0xDBFBB797,0xDAF23754,0x201EC207
  7080.     long        0x3FFF0000,0xDE60F482,0x5E0E9124,0x9E8BE175
  7081.     long        0x3FFF0000,0xE0CCDEEC,0x2A94E110,0x20032C4B
  7082.     long        0x3FFF0000,0xE33F8972,0xBE8A5A50,0x2004DFF5
  7083.     long        0x3FFF0000,0xE5B906E7,0x7C8348A8,0x1E72F47A
  7084.     long        0x3FFF0000,0xE8396A50,0x3C4BDC68,0x1F722F22
  7085.     long        0x3FFF0000,0xEAC0C6E7,0xDD243930,0xA017E945
  7086.     long        0x3FFF0000,0xED4F301E,0xD9942B84,0x1F401A5B
  7087.     long        0x3FFF0000,0xEFE4B99B,0xDCDAF5CC,0x9FB9A9E3
  7088.     long        0x3FFF0000,0xF281773C,0x59FFB138,0x20744C05
  7089.     long        0x3FFF0000,0xF5257D15,0x2486CC2C,0x1F773A19
  7090.     long        0x3FFF0000,0xF7D0DF73,0x0AD13BB8,0x1FFE90D5
  7091.     long        0x3FFF0000,0xFA83B2DB,0x722A033C,0xA041ED22
  7092.     long        0x3FFF0000,0xFD3E0C0C,0xF486C174,0x1F853F3A
  7093.  
  7094.     set        ADJFLAG,L_SCR2
  7095.     set        SCALE,FP_SCR0
  7096.     set        ADJSCALE,FP_SCR1
  7097.     set        SC,FP_SCR0
  7098.     set        ONEBYSC,FP_SCR1
  7099.  
  7100.     global        setox
  7101. setox:
  7102. #--entry point for EXP(X), here X is finite, non-zero, and not NaN's
  7103.  
  7104. #--Step 1.
  7105.     mov.l        (%a0),%d1        # load part of input X
  7106.     and.l        &0x7FFF0000,%d1        # biased expo. of X
  7107.     cmp.l        %d1,&0x3FBE0000        # 2^(-65)
  7108.     bge.b        EXPC1            # normal case
  7109.     bra        EXPSM
  7110.  
  7111. EXPC1:
  7112. #--The case |X| >= 2^(-65)
  7113.     mov.w        4(%a0),%d1        # expo. and partial sig. of |X|
  7114.     cmp.l        %d1,&0x400CB167        # 16380 log2 trunc. 16 bits
  7115.     blt.b        EXPMAIN            # normal case
  7116.     bra        EEXPBIG
  7117.  
  7118. EXPMAIN:
  7119. #--Step 2.
  7120. #--This is the normal branch:    2^(-65) <= |X| < 16380 log2.
  7121.     fmov.x        (%a0),%fp0        # load input from (a0)
  7122.  
  7123.     fmov.x        %fp0,%fp1
  7124.     fmul.s        &0x42B8AA3B,%fp0    # 64/log2 * X
  7125.     fmovm.x        &0xc,-(%sp)        # save fp2 {%fp2/%fp3}
  7126.     mov.l        &0,ADJFLAG(%a6)
  7127.     fmov.l        %fp0,%d1        # N = int( X * 64/log2 )
  7128.     lea        EEXPTBL(%pc),%a1
  7129.     fmov.l        %d1,%fp0        # convert to floating-format
  7130.  
  7131.     mov.l        %d1,L_SCR1(%a6)        # save N temporarily
  7132.     and.l        &0x3F,%d1        # D0 is J = N mod 64
  7133.     lsl.l        &4,%d1
  7134.     add.l        %d1,%a1            # address of 2^(J/64)
  7135.     mov.l        L_SCR1(%a6),%d1
  7136.     asr.l        &6,%d1            # D0 is M
  7137.     add.w        &0x3FFF,%d1        # biased expo. of 2^(M)
  7138.     mov.w        L2(%pc),L_SCR1(%a6)    # prefetch L2, no need in CB
  7139.  
  7140. EXPCONT1:
  7141. #--Step 3.
  7142. #--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
  7143. #--a0 points to 2^(J/64), D0 is biased expo. of 2^(M)
  7144.     fmov.x        %fp0,%fp2
  7145.     fmul.s        &0xBC317218,%fp0    # N * L1, L1 = lead(-log2/64)
  7146.     fmul.x        L2(%pc),%fp2        # N * L2, L1+L2 = -log2/64
  7147.     fadd.x        %fp1,%fp0        # X + N*L1
  7148.     fadd.x        %fp2,%fp0        # fp0 is R, reduced arg.
  7149.  
  7150. #--Step 4.
  7151. #--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
  7152. #-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*A5))))
  7153. #--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
  7154. #--[R+R*S*(A2+S*A4)] + [S*(A1+S*(A3+S*A5))]
  7155.  
  7156.     fmov.x        %fp0,%fp1
  7157.     fmul.x        %fp1,%fp1        # fp1 IS S = R*R
  7158.  
  7159.     fmov.s        &0x3AB60B70,%fp2    # fp2 IS A5
  7160.  
  7161.     fmul.x        %fp1,%fp2        # fp2 IS S*A5
  7162.     fmov.x        %fp1,%fp3
  7163.     fmul.s        &0x3C088895,%fp3    # fp3 IS S*A4
  7164.  
  7165.     fadd.d        EEXPA3(%pc),%fp2    # fp2 IS A3+S*A5
  7166.     fadd.d        EEXPA2(%pc),%fp3    # fp3 IS A2+S*A4
  7167.  
  7168.     fmul.x        %fp1,%fp2        # fp2 IS S*(A3+S*A5)
  7169.     mov.w        %d1,SCALE(%a6)        # SCALE is 2^(M) in extended
  7170.     mov.l        &0x80000000,SCALE+4(%a6)
  7171.     clr.l        SCALE+8(%a6)
  7172.  
  7173.     fmul.x        %fp1,%fp3        # fp3 IS S*(A2+S*A4)
  7174.  
  7175.     fadd.s        &0x3F000000,%fp2    # fp2 IS A1+S*(A3+S*A5)
  7176.     fmul.x        %fp0,%fp3        # fp3 IS R*S*(A2+S*A4)
  7177.  
  7178.     fmul.x        %fp1,%fp2        # fp2 IS S*(A1+S*(A3+S*A5))
  7179.     fadd.x        %fp3,%fp0        # fp0 IS R+R*S*(A2+S*A4),
  7180.  
  7181.     fmov.x        (%a1)+,%fp1        # fp1 is lead. pt. of 2^(J/64)
  7182.     fadd.x        %fp2,%fp0        # fp0 is EXP(R) - 1
  7183.  
  7184. #--Step 5
  7185. #--final reconstruction process
  7186. #--EXP(X) = 2^M * ( 2^(J/64) + 2^(J/64)*(EXP(R)-1) )
  7187.  
  7188.     fmul.x        %fp1,%fp0        # 2^(J/64)*(Exp(R)-1)
  7189.     fmovm.x        (%sp)+,&0x30        # fp2 restored {%fp2/%fp3}
  7190.     fadd.s        (%a1),%fp0        # accurate 2^(J/64)
  7191.  
  7192.     fadd.x        %fp1,%fp0        # 2^(J/64) + 2^(J/64)*...
  7193.     mov.l        ADJFLAG(%a6),%d1
  7194.  
  7195. #--Step 6
  7196.     tst.l        %d1
  7197.     beq.b        NORMAL
  7198. ADJUST:
  7199.     fmul.x        ADJSCALE(%a6),%fp0
  7200. NORMAL:
  7201.     fmov.l        %d0,%fpcr        # restore user FPCR
  7202.     mov.b        &FMUL_OP,%d1        # last inst is MUL
  7203.     fmul.x        SCALE(%a6),%fp0        # multiply 2^(M)
  7204.     bra        t_catch
  7205.  
  7206. EXPSM:
  7207. #--Step 7
  7208.     fmovm.x        (%a0),&0x80        # load X
  7209.     fmov.l        %d0,%fpcr
  7210.     fadd.s        &0x3F800000,%fp0    # 1+X in user mode
  7211.     bra        t_pinx2
  7212.  
  7213. EEXPBIG:
  7214. #--Step 8
  7215.     cmp.l        %d1,&0x400CB27C        # 16480 log2
  7216.     bgt.b        EXP2BIG
  7217. #--Steps 8.2 -- 8.6
  7218.     fmov.x        (%a0),%fp0        # load input from (a0)
  7219.  
  7220.     fmov.x        %fp0,%fp1
  7221.     fmul.s        &0x42B8AA3B,%fp0    # 64/log2 * X
  7222.     fmovm.x        &0xc,-(%sp)        # save fp2 {%fp2/%fp3}
  7223.     mov.l        &1,ADJFLAG(%a6)
  7224.     fmov.l        %fp0,%d1        # N = int( X * 64/log2 )
  7225.     lea        EEXPTBL(%pc),%a1
  7226.     fmov.l        %d1,%fp0        # convert to floating-format
  7227.     mov.l        %d1,L_SCR1(%a6)        # save N temporarily
  7228.     and.l        &0x3F,%d1        # D0 is J = N mod 64
  7229.     lsl.l        &4,%d1
  7230.     add.l        %d1,%a1            # address of 2^(J/64)
  7231.     mov.l        L_SCR1(%a6),%d1
  7232.     asr.l        &6,%d1            # D0 is K
  7233.     mov.l        %d1,L_SCR1(%a6)        # save K temporarily
  7234.     asr.l        &1,%d1            # D0 is M1
  7235.     sub.l        %d1,L_SCR1(%a6)        # a1 is M
  7236.     add.w        &0x3FFF,%d1        # biased expo. of 2^(M1)
  7237.     mov.w        %d1,ADJSCALE(%a6)    # ADJSCALE := 2^(M1)
  7238.     mov.l        &0x80000000,ADJSCALE+4(%a6)
  7239.     clr.l        ADJSCALE+8(%a6)
  7240.     mov.l        L_SCR1(%a6),%d1        # D0 is M
  7241.     add.w        &0x3FFF,%d1        # biased expo. of 2^(M)
  7242.     bra.w        EXPCONT1        # go back to Step 3
  7243.  
  7244. EXP2BIG:
  7245. #--Step 9
  7246.     tst.b        (%a0)            # is X positive or negative?
  7247.     bmi        t_unfl2
  7248.     bra        t_ovfl2
  7249.  
  7250.     global        setoxd
  7251. setoxd:
  7252. #--entry point for EXP(X), X is denormalized
  7253.     mov.l        (%a0),-(%sp)
  7254.     andi.l        &0x80000000,(%sp)
  7255.     ori.l        &0x00800000,(%sp)    # sign(X)*2^(-126)
  7256.  
  7257.     fmov.s        &0x3F800000,%fp0
  7258.  
  7259.     fmov.l        %d0,%fpcr
  7260.     fadd.s        (%sp)+,%fp0
  7261.     bra        t_pinx2
  7262.  
  7263.     global        setoxm1
  7264. setoxm1:
  7265. #--entry point for EXPM1(X), here X is finite, non-zero, non-NaN
  7266.  
  7267. #--Step 1.
  7268. #--Step 1.1
  7269.     mov.l        (%a0),%d1        # load part of input X
  7270.     and.l        &0x7FFF0000,%d1        # biased expo. of X
  7271.     cmp.l        %d1,&0x3FFD0000        # 1/4
  7272.     bge.b        EM1CON1            # |X| >= 1/4
  7273.     bra        EM1SM
  7274.  
  7275. EM1CON1:
  7276. #--Step 1.3
  7277. #--The case |X| >= 1/4
  7278.     mov.w        4(%a0),%d1        # expo. and partial sig. of |X|
  7279.     cmp.l        %d1,&0x4004C215        # 70log2 rounded up to 16 bits
  7280.     ble.b        EM1MAIN            # 1/4 <= |X| <= 70log2
  7281.     bra        EM1BIG
  7282.  
  7283. EM1MAIN:
  7284. #--Step 2.
  7285. #--This is the case:    1/4 <= |X| <= 70 log2.
  7286.     fmov.x        (%a0),%fp0        # load input from (a0)
  7287.  
  7288.     fmov.x        %fp0,%fp1
  7289.     fmul.s        &0x42B8AA3B,%fp0    # 64/log2 * X
  7290.     fmovm.x        &0xc,-(%sp)        # save fp2 {%fp2/%fp3}
  7291.     fmov.l        %fp0,%d1        # N = int( X * 64/log2 )
  7292.     lea        EEXPTBL(%pc),%a1
  7293.     fmov.l        %d1,%fp0        # convert to floating-format
  7294.  
  7295.     mov.l        %d1,L_SCR1(%a6)        # save N temporarily
  7296.     and.l        &0x3F,%d1        # D0 is J = N mod 64
  7297.     lsl.l        &4,%d1
  7298.     add.l        %d1,%a1            # address of 2^(J/64)
  7299.     mov.l        L_SCR1(%a6),%d1
  7300.     asr.l        &6,%d1            # D0 is M
  7301.     mov.l        %d1,L_SCR1(%a6)        # save a copy of M
  7302.  
  7303. #--Step 3.
  7304. #--fp1,fp2 saved on the stack. fp0 is N, fp1 is X,
  7305. #--a0 points to 2^(J/64), D0 and a1 both contain M
  7306.     fmov.x        %fp0,%fp2
  7307.     fmul.s        &0xBC317218,%fp0    # N * L1, L1 = lead(-log2/64)
  7308.     fmul.x        L2(%pc),%fp2        # N * L2, L1+L2 = -log2/64
  7309.     fadd.x        %fp1,%fp0        # X + N*L1
  7310.     fadd.x        %fp2,%fp0        # fp0 is R, reduced arg.
  7311.     add.w        &0x3FFF,%d1        # D0 is biased expo. of 2^M
  7312.  
  7313. #--Step 4.
  7314. #--WE NOW COMPUTE EXP(R)-1 BY A POLYNOMIAL
  7315. #-- R + R*R*(A1 + R*(A2 + R*(A3 + R*(A4 + R*(A5 + R*A6)))))
  7316. #--TO FULLY UTILIZE THE PIPELINE, WE COMPUTE S = R*R
  7317. #--[R*S*(A2+S*(A4+S*A6))] + [R+S*(A1+S*(A3+S*A5))]
  7318.  
  7319.     fmov.x        %fp0,%fp1
  7320.     fmul.x        %fp1,%fp1        # fp1 IS S = R*R
  7321.  
  7322.     fmov.s        &0x3950097B,%fp2    # fp2 IS a6
  7323.  
  7324.     fmul.x        %fp1,%fp2        # fp2 IS S*A6
  7325.     fmov.x        %fp1,%fp3
  7326.     fmul.s        &0x3AB60B6A,%fp3    # fp3 IS S*A5
  7327.  
  7328.     fadd.d        EM1A4(%pc),%fp2        # fp2 IS A4+S*A6
  7329.     fadd.d        EM1A3(%pc),%fp3        # fp3 IS A3+S*A5
  7330.     mov.w        %d1,SC(%a6)        # SC is 2^(M) in extended
  7331.     mov.l        &0x80000000,SC+4(%a6)
  7332.     clr.l        SC+8(%a6)
  7333.  
  7334.     fmul.x        %fp1,%fp2        # fp2 IS S*(A4+S*A6)
  7335.     mov.l        L_SCR1(%a6),%d1        # D0 is    M
  7336.     neg.w        %d1            # D0 is -M
  7337.     fmul.x        %fp1,%fp3        # fp3 IS S*(A3+S*A5)
  7338.     add.w        &0x3FFF,%d1        # biased expo. of 2^(-M)
  7339.     fadd.d        EM1A2(%pc),%fp2        # fp2 IS A2+S*(A4+S*A6)
  7340.     fadd.s        &0x3F000000,%fp3    # fp3 IS A1+S*(A3+S*A5)
  7341.  
  7342.     fmul.x        %fp1,%fp2        # fp2 IS S*(A2+S*(A4+S*A6))
  7343.     or.w        &0x8000,%d1        # signed/expo. of -2^(-M)
  7344.     mov.w        %d1,ONEBYSC(%a6)    # OnebySc is -2^(-M)
  7345.     mov.l        &0x80000000,ONEBYSC+4(%a6)
  7346.     clr.l        ONEBYSC+8(%a6)
  7347.     fmul.x        %fp3,%fp1        # fp1 IS S*(A1+S*(A3+S*A5))
  7348.  
  7349.     fmul.x        %fp0,%fp2        # fp2 IS R*S*(A2+S*(A4+S*A6))
  7350.     fadd.x        %fp1,%fp0        # fp0 IS R+S*(A1+S*(A3+S*A5))
  7351.  
  7352.     fadd.x        %fp2,%fp0        # fp0 IS EXP(R)-1
  7353.  
  7354.     fmovm.x        (%sp)+,&0x30        # fp2 restored {%fp2/%fp3}
  7355.  
  7356. #--Step 5
  7357. #--Compute 2^(J/64)*p
  7358.  
  7359.     fmul.x        (%a1),%fp0        # 2^(J/64)*(Exp(R)-1)
  7360.  
  7361. #--Step 6
  7362. #--Step 6.1
  7363.     mov.l        L_SCR1(%a6),%d1        # retrieve M
  7364.     cmp.l        %d1,&63
  7365.     ble.b        MLE63
  7366. #--Step 6.2    M >= 64
  7367.     fmov.s        12(%a1),%fp1        # fp1 is t
  7368.     fadd.x        ONEBYSC(%a6),%fp1    # fp1 is t+OnebySc
  7369.     fadd.x        %fp1,%fp0        # p+(t+OnebySc), fp1 released
  7370.     fadd.x        (%a1),%fp0        # T+(p+(t+OnebySc))
  7371.     bra        EM1SCALE
  7372. MLE63:
  7373. #--Step 6.3    M <= 63
  7374.     cmp.l        %d1,&-3
  7375.     bge.b        MGEN3
  7376. MLTN3:
  7377. #--Step 6.4    M <= -4
  7378.     fadd.s        12(%a1),%fp0        # p+t
  7379.     fadd.x        (%a1),%fp0        # T+(p+t)
  7380.     fadd.x        ONEBYSC(%a6),%fp0    # OnebySc + (T+(p+t))
  7381.     bra        EM1SCALE
  7382. MGEN3:
  7383. #--Step 6.5    -3 <= M <= 63
  7384.     fmov.x        (%a1)+,%fp1        # fp1 is T
  7385.     fadd.s        (%a1),%fp0        # fp0 is p+t
  7386.     fadd.x        ONEBYSC(%a6),%fp1    # fp1 is T+OnebySc
  7387.     fadd.x        %fp1,%fp0        # (T+OnebySc)+(p+t)
  7388.  
  7389. EM1SCALE:
  7390. #--Step 6.6
  7391.     fmov.l        %d0,%fpcr
  7392.     fmul.x        SC(%a6),%fp0
  7393.     bra        t_inx2
  7394.  
  7395. EM1SM:
  7396. #--Step 7    |X| < 1/4.
  7397.     cmp.l        %d1,&0x3FBE0000        # 2^(-65)
  7398.     bge.b        EM1POLY
  7399.  
  7400. EM1TINY:
  7401. #--Step 8    |X| < 2^(-65)
  7402.     cmp.l        %d1,&0x00330000        # 2^(-16312)
  7403.     blt.b        EM12TINY
  7404. #--Step 8.2
  7405.     mov.l        &0x80010000,SC(%a6)    # SC is -2^(-16382)
  7406.     mov.l        &0x80000000,SC+4(%a6)
  7407.     clr.l        SC+8(%a6)
  7408.     fmov.x        (%a0),%fp0
  7409.     fmov.l        %d0,%fpcr
  7410.     mov.b        &FADD_OP,%d1        # last inst is ADD
  7411.     fadd.x        SC(%a6),%fp0
  7412.     bra        t_catch
  7413.  
  7414. EM12TINY:
  7415. #--Step 8.3
  7416.     fmov.x        (%a0),%fp0
  7417.     fmul.d        TWO140(%pc),%fp0
  7418.     mov.l        &0x80010000,SC(%a6)
  7419.     mov.l        &0x80000000,SC+4(%a6)
  7420.     clr.l        SC+8(%a6)
  7421.     fadd.x        SC(%a6),%fp0
  7422.     fmov.l        %d0,%fpcr
  7423.     mov.b        &FMUL_OP,%d1        # last inst is MUL
  7424.     fmul.d        TWON140(%pc),%fp0
  7425.     bra        t_catch
  7426.  
  7427. EM1POLY:
  7428. #--Step 9    exp(X)-1 by a simple polynomial
  7429.     fmov.x        (%a0),%fp0        # fp0 is X
  7430.     fmul.x        %fp0,%fp0        # fp0 is S := X*X
  7431.     fmovm.x        &0xc,-(%sp)        # save fp2 {%fp2/%fp3}
  7432.     fmov.s        &0x2F30CAA8,%fp1    # fp1 is B12
  7433.     fmul.x        %fp0,%fp1        # fp1 is S*B12
  7434.     fmov.s        &0x310F8290,%fp2    # fp2 is B11
  7435.     fadd.s        &0x32D73220,%fp1    # fp1 is B10+S*B12
  7436.  
  7437.     fmul.x        %fp0,%fp2        # fp2 is S*B11
  7438.     fmul.x        %fp0,%fp1        # fp1 is S*(B10 + ...
  7439.  
  7440.     fadd.s        &0x3493F281,%fp2    # fp2 is B9+S*...
  7441.     fadd.d        EM1B8(%pc),%fp1        # fp1 is B8+S*...
  7442.  
  7443.     fmul.x        %fp0,%fp2        # fp2 is S*(B9+...
  7444.     fmul.x        %fp0,%fp1        # fp1 is S*(B8+...
  7445.  
  7446.     fadd.d        EM1B7(%pc),%fp2        # fp2 is B7+S*...
  7447.     fadd.d        EM1B6(%pc),%fp1        # fp1 is B6+S*...
  7448.  
  7449.     fmul.x        %fp0,%fp2        # fp2 is S*(B7+...
  7450.     fmul.x        %fp0,%fp1        # fp1 is S*(B6+...
  7451.  
  7452.     fadd.d        EM1B5(%pc),%fp2        # fp2 is B5+S*...
  7453.     fadd.d        EM1B4(%pc),%fp1        # fp1 is B4+S*...
  7454.  
  7455.     fmul.x        %fp0,%fp2        # fp2 is S*(B5+...
  7456.     fmul.x        %fp0,%fp1        # fp1 is S*(B4+...
  7457.  
  7458.     fadd.d        EM1B3(%pc),%fp2        # fp2 is B3+S*...
  7459.     fadd.x        EM1B2(%pc),%fp1        # fp1 is B2+S*...
  7460.  
  7461.     fmul.x        %fp0,%fp2        # fp2 is S*(B3+...
  7462.     fmul.x        %fp0,%fp1        # fp1 is S*(B2+...
  7463.  
  7464.     fmul.x        %fp0,%fp2        # fp2 is S*S*(B3+...)
  7465.     fmul.x        (%a0),%fp1        # fp1 is X*S*(B2...
  7466.  
  7467.     fmul.s        &0x3F000000,%fp0    # fp0 is S*B1
  7468.     fadd.x        %fp2,%fp1        # fp1 is Q
  7469.  
  7470.     fmovm.x        (%sp)+,&0x30        # fp2 restored {%fp2/%fp3}
  7471.  
  7472.     fadd.x        %fp1,%fp0        # fp0 is S*B1+Q
  7473.  
  7474.     fmov.l        %d0,%fpcr
  7475.     fadd.x        (%a0),%fp0
  7476.     bra        t_inx2
  7477.  
  7478. EM1BIG:
  7479. #--Step 10    |X| > 70 log2
  7480.     mov.l        (%a0),%d1
  7481.     cmp.l        %d1,&0
  7482.     bgt.w        EXPC1
  7483. #--Step 10.2
  7484.     fmov.s        &0xBF800000,%fp0    # fp0 is -1
  7485.     fmov.l        %d0,%fpcr
  7486.     fadd.s        &0x00800000,%fp0    # -1 + 2^(-126)
  7487.     bra        t_minx2
  7488.  
  7489.     global        setoxm1d
  7490. setoxm1d:
  7491. #--entry point for EXPM1(X), here X is denormalized
  7492. #--Step 0.
  7493.     bra        t_extdnrm
  7494.  
  7495. #########################################################################
  7496. # sgetexp():  returns the exponent portion of the input argument.    #
  7497. #          The exponent bias is removed and the exponent value is    #
  7498. #          returned as an extended precision number in fp0.        #
  7499. # sgetexpd(): handles denormalized numbers.                 #
  7500. #                                    #
  7501. # sgetman():  extracts the mantissa of the input argument. The         #
  7502. #          mantissa is converted to an extended precision number w/     #
  7503. #          an exponent of $3fff and is returned in fp0. The range of #
  7504. #          the result is [1.0 - 2.0).                #
  7505. # sgetmand(): handles denormalized numbers.                #
  7506. #                                    #
  7507. # INPUT *************************************************************** #
  7508. #    a0  = pointer to extended precision input            #
  7509. #                                    #
  7510. # OUTPUT ************************************************************** #
  7511. #    fp0 = exponent(X) or mantissa(X)                #
  7512. #                                    #
  7513. #########################################################################
  7514.  
  7515.     global        sgetexp
  7516. sgetexp:
  7517.     mov.w        SRC_EX(%a0),%d0        # get the exponent
  7518.     bclr        &0xf,%d0        # clear the sign bit
  7519.     subi.w        &0x3fff,%d0        # subtract off the bias
  7520.     fmov.w        %d0,%fp0        # return exp in fp0
  7521.     blt.b        sgetexpn        # it's negative
  7522.     rts
  7523.  
  7524. sgetexpn:
  7525.     mov.b        &neg_bmask,FPSR_CC(%a6)    # set 'N' ccode bit
  7526.     rts
  7527.  
  7528.     global        sgetexpd
  7529. sgetexpd:
  7530.     bsr.l        norm            # normalize
  7531.     neg.w        %d0            # new exp = -(shft amt)
  7532.     subi.w        &0x3fff,%d0        # subtract off the bias
  7533.     fmov.w        %d0,%fp0        # return exp in fp0
  7534.     mov.b        &neg_bmask,FPSR_CC(%a6)    # set 'N' ccode bit
  7535.     rts
  7536.  
  7537.     global        sgetman
  7538. sgetman:
  7539.     mov.w        SRC_EX(%a0),%d0        # get the exp
  7540.     ori.w        &0x7fff,%d0        # clear old exp
  7541.     bclr        &0xe,%d0        # make it the new exp +-3fff
  7542.  
  7543. # here, we build the result in a tmp location so as not to disturb the input
  7544.     mov.l        SRC_HI(%a0),FP_SCR0_HI(%a6) # copy to tmp loc
  7545.     mov.l        SRC_LO(%a0),FP_SCR0_LO(%a6) # copy to tmp loc
  7546.     mov.w        %d0,FP_SCR0_EX(%a6)    # insert new exponent
  7547.     fmov.x        FP_SCR0(%a6),%fp0    # put new value back in fp0
  7548.     bmi.b        sgetmann        # it's negative
  7549.     rts
  7550.  
  7551. sgetmann:
  7552.     mov.b        &neg_bmask,FPSR_CC(%a6)    # set 'N' ccode bit
  7553.     rts
  7554.  
  7555. #
  7556. # For denormalized numbers, shift the mantissa until the j-bit = 1,
  7557. # then load the exponent with +/1 $3fff.
  7558. #
  7559.     global        sgetmand
  7560. sgetmand:
  7561.     bsr.l        norm            # normalize exponent
  7562.     bra.b        sgetman
  7563.  
  7564. #########################################################################
  7565. # scosh():  computes the hyperbolic cosine of a normalized input    #
  7566. # scoshd(): computes the hyperbolic cosine of a denormalized input    #
  7567. #                                    #
  7568. # INPUT ***************************************************************    #
  7569. #    a0 = pointer to extended precision input            #
  7570. #    d0 = round precision,mode                    #
  7571. #                                    #
  7572. # OUTPUT **************************************************************    #
  7573. #    fp0 = cosh(X)                            #
  7574. #                                    #
  7575. # ACCURACY and MONOTONICITY *******************************************    #
  7576. #    The returned result is within 3 ulps in 64 significant bit,     #
  7577. #    i.e. within 0.5001 ulp to 53 bits if the result is subsequently    #
  7578. #    rounded to double precision. The result is provably monotonic     #
  7579. #    in double precision.                        #
  7580. #                                    #
  7581. # ALGORITHM ***********************************************************    #
  7582. #                                    #
  7583. #    COSH                                #
  7584. #    1. If |X| > 16380 log2, go to 3.                #
  7585. #                                    #
  7586. #    2. (|X| <= 16380 log2) Cosh(X) is obtained by the formulae    #
  7587. #        y = |X|, z = exp(Y), and                #
  7588. #        cosh(X) = (1/2)*( z + 1/z ).                #
  7589. #        Exit.                            #
  7590. #                                    #
  7591. #    3. (|X| > 16380 log2). If |X| > 16480 log2, go to 5.        #
  7592. #                                    #
  7593. #    4. (16380 log2 < |X| <= 16480 log2)                #
  7594. #        cosh(X) = sign(X) * exp(|X|)/2.                #
  7595. #        However, invoking exp(|X|) may cause premature         #
  7596. #        overflow. Thus, we calculate sinh(X) as follows:    #
  7597. #        Y    := |X|                        #
  7598. #        Fact    :=    2**(16380)                #
  7599. #        Y'    := Y - 16381 log2                #
  7600. #        cosh(X) := Fact * exp(Y').                #
  7601. #        Exit.                            #
  7602. #                                    #
  7603. #    5. (|X| > 16480 log2) sinh(X) must overflow. Return        #
  7604. #        Huge*Huge to generate overflow and an infinity with    #
  7605. #        the appropriate sign. Huge is the largest finite number    #
  7606. #        in extended format. Exit.                #
  7607. #                                    #
  7608. #########################################################################
  7609.  
  7610. TWO16380:
  7611.     long        0x7FFB0000,0x80000000,0x00000000,0x00000000
  7612.  
  7613.     global        scosh
  7614. scosh:
  7615.     fmov.x        (%a0),%fp0        # LOAD INPUT
  7616.  
  7617.     mov.l        (%a0),%d1
  7618.     mov.w        4(%a0),%d1
  7619.     and.l        &0x7FFFFFFF,%d1
  7620.     cmp.l        %d1,&0x400CB167
  7621.     bgt.b        COSHBIG
  7622.  
  7623. #--THIS IS THE USUAL CASE, |X| < 16380 LOG2
  7624. #--COSH(X) = (1/2) * ( EXP(X) + 1/EXP(X) )
  7625.  
  7626.     fabs.x        %fp0            # |X|
  7627.  
  7628.     mov.l        %d0,-(%sp)
  7629.     clr.l        %d0
  7630.     fmovm.x        &0x01,-(%sp)        # save |X| to stack
  7631.     lea        (%sp),%a0        # pass ptr to |X|
  7632.     bsr        setox            # FP0 IS EXP(|X|)
  7633.     add.l        &0xc,%sp        # erase |X| from stack
  7634.     fmul.s        &0x3F000000,%fp0    # (1/2)EXP(|X|)
  7635.     mov.l        (%sp)+,%d0
  7636.  
  7637.     fmov.s        &0x3E800000,%fp1    # (1/4)
  7638.     fdiv.x        %fp0,%fp1        # 1/(2 EXP(|X|))
  7639.  
  7640.     fmov.l        %d0,%fpcr
  7641.     mov.b        &FADD_OP,%d1        # last inst is ADD
  7642.     fadd.x        %fp1,%fp0
  7643.     bra        t_catch
  7644.  
  7645. COSHBIG:
  7646.     cmp.l        %d1,&0x400CB2B3
  7647.     bgt.b        COSHHUGE
  7648.  
  7649.     fabs.x        %fp0
  7650.     fsub.d        T1(%pc),%fp0        # (|X|-16381LOG2_LEAD)
  7651.     fsub.d        T2(%pc),%fp0        # |X| - 16381 LOG2, ACCURATE
  7652.  
  7653.     mov.l        %d0,-(%sp)
  7654.     clr.l        %d0
  7655.     fmovm.x        &0x01,-(%sp)        # save fp0 to stack
  7656.     lea        (%sp),%a0        # pass ptr to fp0
  7657.     bsr        setox
  7658.     add.l        &0xc,%sp        # clear fp0 from stack
  7659.     mov.l        (%sp)+,%d0
  7660.  
  7661.     fmov.l        %d0,%fpcr
  7662.     mov.b        &FMUL_OP,%d1        # last inst is MUL
  7663.     fmul.x        TWO16380(%pc),%fp0
  7664.     bra        t_catch
  7665.  
  7666. COSHHUGE:
  7667.     bra        t_ovfl2
  7668.  
  7669.     global        scoshd
  7670. #--COSH(X) = 1 FOR DENORMALIZED X
  7671. scoshd:
  7672.     fmov.s        &0x3F800000,%fp0
  7673.  
  7674.     fmov.l        %d0,%fpcr
  7675.     fadd.s        &0x00800000,%fp0
  7676.     bra        t_pinx2
  7677.  
  7678. #########################################################################
  7679. # ssinh():  computes the hyperbolic sine of a normalized input        #
  7680. # ssinhd(): computes the hyperbolic sine of a denormalized input    #
  7681. #                                    #
  7682. # INPUT *************************************************************** #
  7683. #    a0 = pointer to extended precision input            #
  7684. #    d0 = round precision,mode                    #
  7685. #                                    #
  7686. # OUTPUT ************************************************************** #
  7687. #    fp0 = sinh(X)                            #
  7688. #                                    #
  7689. # ACCURACY and MONOTONICITY *******************************************    #
  7690. #    The returned result is within 3 ulps in 64 significant bit,     #
  7691. #    i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
  7692. #    rounded to double precision. The result is provably monotonic    #
  7693. #    in double precision.                        #
  7694. #                                    #
  7695. # ALGORITHM *********************************************************** #
  7696. #                                    #
  7697. #       SINH                                #
  7698. #       1. If |X| > 16380 log2, go to 3.                #
  7699. #                                    #
  7700. #       2. (|X| <= 16380 log2) Sinh(X) is obtained by the formula    #
  7701. #               y = |X|, sgn = sign(X), and z = expm1(Y),        #
  7702. #               sinh(X) = sgn*(1/2)*( z + z/(1+z) ).            #
  7703. #          Exit.                            #
  7704. #                                    #
  7705. #       3. If |X| > 16480 log2, go to 5.                #
  7706. #                                    #
  7707. #       4. (16380 log2 < |X| <= 16480 log2)                #
  7708. #               sinh(X) = sign(X) * exp(|X|)/2.                #
  7709. #          However, invoking exp(|X|) may cause premature overflow.    #
  7710. #          Thus, we calculate sinh(X) as follows:            #
  7711. #             Y       := |X|                        #
  7712. #             sgn     := sign(X)                    #
  7713. #             sgnFact := sgn * 2**(16380)                #
  7714. #             Y'      := Y - 16381 log2                    #
  7715. #             sinh(X) := sgnFact * exp(Y').                #
  7716. #          Exit.                            #
  7717. #                                    #
  7718. #       5. (|X| > 16480 log2) sinh(X) must overflow. Return        #
  7719. #          sign(X)*Huge*Huge to generate overflow and an infinity with    #
  7720. #          the appropriate sign. Huge is the largest finite number in    #
  7721. #          extended format. Exit.                    #
  7722. #                                    #
  7723. #########################################################################
  7724.  
  7725.     global        ssinh
  7726. ssinh:
  7727.     fmov.x        (%a0),%fp0        # LOAD INPUT
  7728.  
  7729.     mov.l        (%a0),%d1
  7730.     mov.w        4(%a0),%d1
  7731.     mov.l        %d1,%a1            # save (compacted) operand
  7732.     and.l        &0x7FFFFFFF,%d1
  7733.     cmp.l        %d1,&0x400CB167
  7734.     bgt.b        SINHBIG
  7735.  
  7736. #--THIS IS THE USUAL CASE, |X| < 16380 LOG2
  7737. #--Y = |X|, Z = EXPM1(Y), SINH(X) = SIGN(X)*(1/2)*( Z + Z/(1+Z) )
  7738.  
  7739.     fabs.x        %fp0            # Y = |X|
  7740.  
  7741.     movm.l        &0x8040,-(%sp)        # {a1/d0}
  7742.     fmovm.x        &0x01,-(%sp)        # save Y on stack
  7743.     lea        (%sp),%a0        # pass ptr to Y
  7744.     clr.l        %d0
  7745.     bsr        setoxm1            # FP0 IS Z = EXPM1(Y)
  7746.     add.l        &0xc,%sp        # clear Y from stack
  7747.     fmov.l        &0,%fpcr
  7748.     movm.l        (%sp)+,&0x0201        # {a1/d0}
  7749.  
  7750.     fmov.x        %fp0,%fp1
  7751.     fadd.s        &0x3F800000,%fp1    # 1+Z
  7752.     fmov.x        %fp0,-(%sp)
  7753.     fdiv.x        %fp1,%fp0        # Z/(1+Z)
  7754.     mov.l        %a1,%d1
  7755.     and.l        &0x80000000,%d1
  7756.     or.l        &0x3F000000,%d1
  7757.     fadd.x        (%sp)+,%fp0
  7758.     mov.l        %d1,-(%sp)
  7759.  
  7760.     fmov.l        %d0,%fpcr
  7761.     mov.b        &FMUL_OP,%d1        # last inst is MUL
  7762.     fmul.s        (%sp)+,%fp0        # last fp inst - possible exceptions set
  7763.     bra        t_catch
  7764.  
  7765. SINHBIG:
  7766.     cmp.l        %d1,&0x400CB2B3
  7767.     bgt        t_ovfl
  7768.     fabs.x        %fp0
  7769.     fsub.d        T1(%pc),%fp0        # (|X|-16381LOG2_LEAD)
  7770.     mov.l        &0,-(%sp)
  7771.     mov.l        &0x80000000,-(%sp)
  7772.     mov.l        %a1,%d1
  7773.     and.l        &0x80000000,%d1
  7774.     or.l        &0x7FFB0000,%d1
  7775.     mov.l        %d1,-(%sp)        # EXTENDED FMT
  7776.     fsub.d        T2(%pc),%fp0        # |X| - 16381 LOG2, ACCURATE
  7777.  
  7778.     mov.l        %d0,-(%sp)
  7779.     clr.l        %d0
  7780.     fmovm.x        &0x01,-(%sp)        # save fp0 on stack
  7781.     lea        (%sp),%a0        # pass ptr to fp0
  7782.     bsr        setox
  7783.     add.l        &0xc,%sp        # clear fp0 from stack
  7784.  
  7785.     mov.l        (%sp)+,%d0
  7786.     fmov.l        %d0,%fpcr
  7787.     mov.b        &FMUL_OP,%d1        # last inst is MUL
  7788.     fmul.x        (%sp)+,%fp0        # possible exception
  7789.     bra        t_catch
  7790.  
  7791.     global        ssinhd
  7792. #--SINH(X) = X FOR DENORMALIZED X
  7793. ssinhd:
  7794.     bra        t_extdnrm
  7795.  
  7796. #########################################################################
  7797. # stanh():  computes the hyperbolic tangent of a normalized input    #
  7798. # stanhd(): computes the hyperbolic tangent of a denormalized input    #
  7799. #                                    #
  7800. # INPUT ***************************************************************    #
  7801. #    a0 = pointer to extended precision input            #
  7802. #    d0 = round precision,mode                    #
  7803. #                                    #
  7804. # OUTPUT **************************************************************    #
  7805. #    fp0 = tanh(X)                            #
  7806. #                                    #
  7807. # ACCURACY and MONOTONICITY *******************************************    #
  7808. #    The returned result is within 3 ulps in 64 significant bit,     #
  7809. #    i.e. within 0.5001 ulp to 53 bits if the result is subsequently #
  7810. #    rounded to double precision. The result is provably monotonic    #
  7811. #    in double precision.                        #
  7812. #                                    #
  7813. # ALGORITHM ***********************************************************    #
  7814. #                                    #
  7815. #    TANH                                #
  7816. #    1. If |X| >= (5/2) log2 or |X| <= 2**(-40), go to 3.        #
  7817. #                                    #
  7818. #    2. (2**(-40) < |X| < (5/2) log2) Calculate tanh(X) by        #
  7819. #        sgn := sign(X), y := 2|X|, z := expm1(Y), and        #
  7820. #        tanh(X) = sgn*( z/(2+z) ).                #
  7821. #        Exit.                            #
  7822. #                                    #
  7823. #    3. (|X| <= 2**(-40) or |X| >= (5/2) log2). If |X| < 1,        #
  7824. #        go to 7.                        #
  7825. #                                    #
  7826. #    4. (|X| >= (5/2) log2) If |X| >= 50 log2, go to 6.        #
  7827. #                                    #
  7828. #    5. ((5/2) log2 <= |X| < 50 log2) Calculate tanh(X) by        #
  7829. #        sgn := sign(X), y := 2|X|, z := exp(Y),            #
  7830. #        tanh(X) = sgn - [ sgn*2/(1+z) ].            #
  7831. #        Exit.                            #
  7832. #                                    #
  7833. #    6. (|X| >= 50 log2) Tanh(X) = +-1 (round to nearest). Thus, we    #
  7834. #        calculate Tanh(X) by                    #
  7835. #        sgn := sign(X), Tiny := 2**(-126),            #
  7836. #        tanh(X) := sgn - sgn*Tiny.                #
  7837. #        Exit.                            #
  7838. #                                    #
  7839. #    7. (|X| < 2**(-40)). Tanh(X) = X.    Exit.            #
  7840. #                                    #
  7841. #########################################################################
  7842.  
  7843.     set        X,FP_SCR0
  7844.     set        XFRAC,X+4
  7845.  
  7846.     set        SGN,L_SCR3
  7847.  
  7848.     set        V,FP_SCR0
  7849.  
  7850.     global        stanh
  7851. stanh:
  7852.     fmov.x        (%a0),%fp0        # LOAD INPUT
  7853.  
  7854.     fmov.x        %fp0,X(%a6)
  7855.     mov.l        (%a0),%d1
  7856.     mov.w        4(%a0),%d1
  7857.     mov.l        %d1,X(%a6)
  7858.     and.l        &0x7FFFFFFF,%d1
  7859.     cmp.l        %d1, &0x3fd78000    # is |X| < 2^(-40)?
  7860.     blt.w        TANHBORS        # yes
  7861.     cmp.l        %d1, &0x3fffddce    # is |X| > (5/2)LOG2?
  7862.     bgt.w        TANHBORS        # yes
  7863.  
  7864. #--THIS IS THE USUAL CASE
  7865. #--Y = 2|X|, Z = EXPM1(Y), TANH(X) = SIGN(X) * Z / (Z+2).
  7866.  
  7867.     mov.l        X(%a6),%d1
  7868.     mov.l        %d1,SGN(%a6)
  7869.     and.l        &0x7FFF0000,%d1
  7870.     add.l        &0x00010000,%d1        # EXPONENT OF 2|X|
  7871.     mov.l        %d1,X(%a6)
  7872.     and.l        &0x80000000,SGN(%a6)
  7873.     fmov.x        X(%a6),%fp0        # FP0 IS Y = 2|X|
  7874.  
  7875.     mov.l        %d0,-(%sp)
  7876.     clr.l        %d0
  7877.     fmovm.x        &0x1,-(%sp)        # save Y on stack
  7878.     lea        (%sp),%a0        # pass ptr to Y
  7879.     bsr        setoxm1            # FP0 IS Z = EXPM1(Y)
  7880.     add.l        &0xc,%sp        # clear Y from stack
  7881.     mov.l        (%sp)+,%d0
  7882.  
  7883.     fmov.x        %fp0,%fp1
  7884.     fadd.s        &0x40000000,%fp1    # Z+2
  7885.     mov.l        SGN(%a6),%d1
  7886.     fmov.x        %fp1,V(%a6)
  7887.     eor.l        %d1,V(%a6)
  7888.  
  7889.     fmov.l        %d0,%fpcr        # restore users round prec,mode
  7890.     fdiv.x        V(%a6),%fp0
  7891.     bra        t_inx2
  7892.  
  7893. TANHBORS:
  7894.     cmp.l        %d1,&0x3FFF8000
  7895.     blt.w        TANHSM
  7896.  
  7897.     cmp.l        %d1,&0x40048AA1
  7898.     bgt.w        TANHHUGE
  7899.  
  7900. #-- (5/2) LOG2 < |X| < 50 LOG2,
  7901. #--TANH(X) = 1 - (2/[EXP(2X)+1]). LET Y = 2|X|, SGN = SIGN(X),
  7902. #--TANH(X) = SGN -    SGN*2/[EXP(Y)+1].
  7903.  
  7904.     mov.l        X(%a6),%d1
  7905.     mov.l        %d1,SGN(%a6)
  7906.     and.l        &0x7FFF0000,%d1
  7907.     add.l        &0x00010000,%d1        # EXPO OF 2|X|
  7908.     mov.l        %d1,X(%a6)        # Y = 2|X|
  7909.     and.l        &0x80000000,SGN(%a6)
  7910.     mov.l        SGN(%a6),%d1
  7911.     fmov.x        X(%a6),%fp0        # Y = 2|X|
  7912.  
  7913.     mov.l        %d0,-(%sp)
  7914.     clr.l        %d0
  7915.     fmovm.x        &0x01,-(%sp)        # save Y on stack
  7916.     lea        (%sp),%a0        # pass ptr to Y
  7917.     bsr        setox            # FP0 IS EXP(Y)
  7918.     add.l        &0xc,%sp        # clear Y from stack
  7919.     mov.l        (%sp)+,%d0
  7920.     mov.l        SGN(%a6),%d1
  7921.     fadd.s        &0x3F800000,%fp0    # EXP(Y)+1
  7922.  
  7923.     eor.l        &0xC0000000,%d1        # -SIGN(X)*2
  7924.     fmov.s        %d1,%fp1        # -SIGN(X)*2 IN SGL FMT
  7925.     fdiv.x        %fp0,%fp1        # -SIGN(X)2 / [EXP(Y)+1 ]
  7926.  
  7927.     mov.l        SGN(%a6),%d1
  7928.     or.l        &0x3F800000,%d1        # SGN
  7929.     fmov.s        %d1,%fp0        # SGN IN SGL FMT
  7930.  
  7931.     fmov.l        %d0,%fpcr        # restore users round prec,mode
  7932.     mov.b        &FADD_OP,%d1        # last inst is ADD
  7933.     fadd.x        %fp1,%fp0
  7934.     bra        t_inx2
  7935.  
  7936. TANHSM:
  7937.     fmov.l        %d0,%fpcr        # restore users round prec,mode
  7938.     mov.b        &FMOV_OP,%d1        # last inst is MOVE
  7939.     fmov.x        X(%a6),%fp0        # last inst - possible exception set
  7940.     bra        t_catch
  7941.  
  7942. #---RETURN SGN(X) - SGN(X)EPS
  7943. TANHHUGE:
  7944.     mov.l        X(%a6),%d1
  7945.     and.l        &0x80000000,%d1
  7946.     or.l        &0x3F800000,%d1
  7947.     fmov.s        %d1,%fp0
  7948.     and.l        &0x80000000,%d1
  7949.     eor.l        &0x80800000,%d1        # -SIGN(X)*EPS
  7950.  
  7951.     fmov.l        %d0,%fpcr        # restore users round prec,mode
  7952.     fadd.s        %d1,%fp0
  7953.     bra        t_inx2
  7954.  
  7955.     global        stanhd
  7956. #--TANH(X) = X FOR DENORMALIZED X
  7957. stanhd:
  7958.     bra        t_extdnrm
  7959.  
  7960. #########################################################################
  7961. # slogn():    computes the natural logarithm of a normalized input    #
  7962. # slognd():   computes the natural logarithm of a denormalized input    #
  7963. # slognp1():  computes the log(1+X) of a normalized input        #
  7964. # slognp1d(): computes the log(1+X) of a denormalized input        #
  7965. #                                    #
  7966. # INPUT ***************************************************************    #
  7967. #    a0 = pointer to extended precision input            #
  7968. #    d0 = round precision,mode                    #
  7969. #                                    #
  7970. # OUTPUT **************************************************************    #
  7971. #    fp0 = log(X) or log(1+X)                    #
  7972. #                                    #
  7973. # ACCURACY and MONOTONICITY *******************************************    #
  7974. #    The returned result is within 2 ulps in 64 significant bit,     #
  7975. #    i.e. within 0.5001 ulp to 53 bits if the result is subsequently    #
  7976. #    rounded to double precision. The result is provably monotonic    #
  7977. #    in double precision.                        #
  7978. #                                    #
  7979. # ALGORITHM ***********************************************************    #
  7980. #    LOGN:                                #
  7981. #    Step 1. If |X-1| < 1/16, approximate log(X) by an odd         #
  7982. #        polynomial in u, where u = 2(X-1)/(X+1). Otherwise,     #
  7983. #        move on to Step 2.                    #
  7984. #                                    #
  7985. #    Step 2. X = 2**k * Y where 1 <= Y < 2. Define F to be the first    #
  7986. #        seven significant bits of Y plus 2**(-7), i.e.         #
  7987. #        F = 1.xxxxxx1 in base 2 where the six "x" match those     #
  7988. #        of Y. Note that |Y-F| <= 2**(-7).            #
  7989. #                                    #
  7990. #    Step 3. Define u = (Y-F)/F. Approximate log(1+u) by a         #
  7991. #        polynomial in u, log(1+u) = poly.            #
  7992. #                                    #
  7993. #    Step 4. Reconstruct                         #
  7994. #        log(X) = log( 2**k * Y ) = k*log(2) + log(F) + log(1+u)    #
  7995. #        by k*log(2) + (log(F) + poly). The values of log(F) are    #
  7996. #        calculated beforehand and stored in the program.    #
  7997. #                                    #
  7998. #    lognp1:                                #
  7999. #    Step 1: If |X| < 1/16, approximate log(1+X) by an odd         #
  8000. #        polynomial in u where u = 2X/(2+X). Otherwise, move on    #
  8001. #        to Step 2.                        #
  8002. #                                    #
  8003. #    Step 2: Let 1+X = 2**k * Y, where 1 <= Y < 2. Define F as done    #
  8004. #        in Step 2 of the algorithm for LOGN and compute     #
  8005. #        log(1+X) as k*log(2) + log(F) + poly where poly     #
  8006. #        approximates log(1+u), u = (Y-F)/F.             #
  8007. #                                    #
  8008. #    Implementation Notes:                        #
  8009. #    Note 1. There are 64 different possible values for F, thus 64     #
  8010. #        log(F)'s need to be tabulated. Moreover, the values of    #
  8011. #        1/F are also tabulated so that the division in (Y-F)/F    #
  8012. #        can be performed by a multiplication.            #
  8013. #                                    #
  8014. #    Note 2. In Step 2 of lognp1, in order to preserved accuracy,     #
  8015. #        the value Y-F has to be calculated carefully when     #
  8016. #        1/2 <= X < 3/2.                     #
  8017. #                                    #
  8018. #    Note 3. To fully exploit the pipeline, polynomials are usually     #
  8019. #        separated into two parts evaluated independently before    #
  8020. #        being added up.                        #
  8021. #                                    #
  8022. #########################################################################
  8023. LOGOF2:
  8024.     long        0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
  8025.  
  8026. one:
  8027.     long        0x3F800000
  8028. zero:
  8029.     long        0x00000000
  8030. infty:
  8031.     long        0x7F800000
  8032. negone:
  8033.     long        0xBF800000
  8034.  
  8035. LOGA6:
  8036.     long        0x3FC2499A,0xB5E4040B
  8037. LOGA5:
  8038.     long        0xBFC555B5,0x848CB7DB
  8039.  
  8040. LOGA4:
  8041.     long        0x3FC99999,0x987D8730
  8042. LOGA3:
  8043.     long        0xBFCFFFFF,0xFF6F7E97
  8044.  
  8045. LOGA2:
  8046.     long        0x3FD55555,0x555555A4
  8047. LOGA1:
  8048.     long        0xBFE00000,0x00000008
  8049.  
  8050. LOGB5:
  8051.     long        0x3F175496,0xADD7DAD6
  8052. LOGB4:
  8053.     long        0x3F3C71C2,0xFE80C7E0
  8054.  
  8055. LOGB3:
  8056.     long        0x3F624924,0x928BCCFF
  8057. LOGB2:
  8058.     long        0x3F899999,0x999995EC
  8059.  
  8060. LOGB1:
  8061.     long        0x3FB55555,0x55555555
  8062. TWO:
  8063.     long        0x40000000,0x00000000
  8064.  
  8065. LTHOLD:
  8066.     long        0x3f990000,0x80000000,0x00000000,0x00000000
  8067.  
  8068. LOGTBL:
  8069.     long        0x3FFE0000,0xFE03F80F,0xE03F80FE,0x00000000
  8070.     long        0x3FF70000,0xFF015358,0x833C47E2,0x00000000
  8071.     long        0x3FFE0000,0xFA232CF2,0x52138AC0,0x00000000
  8072.     long        0x3FF90000,0xBDC8D83E,0xAD88D549,0x00000000
  8073.     long        0x3FFE0000,0xF6603D98,0x0F6603DA,0x00000000
  8074.     long        0x3FFA0000,0x9CF43DCF,0xF5EAFD48,0x00000000
  8075.     long        0x3FFE0000,0xF2B9D648,0x0F2B9D65,0x00000000
  8076.     long        0x3FFA0000,0xDA16EB88,0xCB8DF614,0x00000000
  8077.     long        0x3FFE0000,0xEF2EB71F,0xC4345238,0x00000000
  8078.     long        0x3FFB0000,0x8B29B775,0x1BD70743,0x00000000
  8079.     long        0x3FFE0000,0xEBBDB2A5,0xC1619C8C,0x00000000
  8080.     long        0x3FFB0000,0xA8D839F8,0x30C1FB49,0x00000000
  8081.     long        0x3FFE0000,0xE865AC7B,0x7603A197,0x00000000
  8082.     long        0x3FFB0000,0xC61A2EB1,0x8CD907AD,0x00000000
  8083.     long        0x3FFE0000,0xE525982A,0xF70C880E,0x00000000
  8084.     long        0x3FFB0000,0xE2F2A47A,0xDE3A18AF,0x00000000
  8085.     long        0x3FFE0000,0xE1FC780E,0x1FC780E2,0x00000000
  8086.     long        0x3FFB0000,0xFF64898E,0xDF55D551,0x00000000
  8087.     long        0x3FFE0000,0xDEE95C4C,0xA037BA57,0x00000000
  8088.     long        0x3FFC0000,0x8DB956A9,0x7B3D0148,0x00000000
  8089.     long        0x3FFE0000,0xDBEB61EE,0xD19C5958,0x00000000
  8090.     long        0x3FFC0000,0x9B8FE100,0xF47BA1DE,0x00000000
  8091.     long        0x3FFE0000,0xD901B203,0x6406C80E,0x00000000
  8092.     long        0x3FFC0000,0xA9372F1D,0x0DA1BD17,0x00000000
  8093.     long        0x3FFE0000,0xD62B80D6,0x2B80D62C,0x00000000
  8094.     long        0x3FFC0000,0xB6B07F38,0xCE90E46B,0x00000000
  8095.     long        0x3FFE0000,0xD3680D36,0x80D3680D,0x00000000
  8096.     long        0x3FFC0000,0xC3FD0329,0x06488481,0x00000000
  8097.     long        0x3FFE0000,0xD0B69FCB,0xD2580D0B,0x00000000
  8098.     long        0x3FFC0000,0xD11DE0FF,0x15AB18CA,0x00000000
  8099.     long        0x3FFE0000,0xCE168A77,0x25080CE1,0x00000000
  8100.     long        0x3FFC0000,0xDE1433A1,0x6C66B150,0x00000000
  8101.     long        0x3FFE0000,0xCB8727C0,0x65C393E0,0x00000000
  8102.     long        0x3FFC0000,0xEAE10B5A,0x7DDC8ADD,0x00000000
  8103.     long        0x3FFE0000,0xC907DA4E,0x871146AD,0x00000000
  8104.     long        0x3FFC0000,0xF7856E5E,0xE2C9B291,0x00000000
  8105.     long        0x3FFE0000,0xC6980C69,0x80C6980C,0x00000000
  8106.     long        0x3FFD0000,0x82012CA5,0xA68206D7,0x00000000
  8107.     long        0x3FFE0000,0xC4372F85,0x5D824CA6,0x00000000
  8108.     long        0x3FFD0000,0x882C5FCD,0x7256A8C5,0x00000000
  8109.     long        0x3FFE0000,0xC1E4BBD5,0x95F6E947,0x00000000
  8110.     long        0x3FFD0000,0x8E44C60B,0x4CCFD7DE,0x00000000
  8111.     long        0x3FFE0000,0xBFA02FE8,0x0BFA02FF,0x00000000
  8112.     long        0x3FFD0000,0x944AD09E,0xF4351AF6,0x00000000
  8113.     long        0x3FFE0000,0xBD691047,0x07661AA3,0x00000000
  8114.     long        0x3FFD0000,0x9A3EECD4,0xC3EAA6B2,0x00000000
  8115.     long        0x3FFE0000,0xBB3EE721,0xA54D880C,0x00000000
  8116.     long        0x3FFD0000,0xA0218434,0x353F1DE8,0x00000000
  8117.     long        0x3FFE0000,0xB92143FA,0x36F5E02E,0x00000000
  8118.     long        0x3FFD0000,0xA5F2FCAB,0xBBC506DA,0x00000000
  8119.     long        0x3FFE0000,0xB70FBB5A,0x19BE3659,0x00000000
  8120.     long        0x3FFD0000,0xABB3B8BA,0x2AD362A5,0x00000000
  8121.     long        0x3FFE0000,0xB509E68A,0x9B94821F,0x00000000
  8122.     long        0x3FFD0000,0xB1641795,0xCE3CA97B,0x00000000
  8123.     long        0x3FFE0000,0xB30F6352,0x8917C80B,0x00000000
  8124.     long        0x3FFD0000,0xB7047551,0x5D0F1C61,0x00000000
  8125.     long        0x3FFE0000,0xB11FD3B8,0x0B11FD3C,0x00000000
  8126.     long        0x3FFD0000,0xBC952AFE,0xEA3D13E1,0x00000000
  8127.     long        0x3FFE0000,0xAF3ADDC6,0x80AF3ADE,0x00000000
  8128.     long        0x3FFD0000,0xC2168ED0,0xF458BA4A,0x00000000
  8129.     long        0x3FFE0000,0xAD602B58,0x0AD602B6,0x00000000
  8130.     long        0x3FFD0000,0xC788F439,0xB3163BF1,0x00000000
  8131.     long        0x3FFE0000,0xAB8F69E2,0x8359CD11,0x00000000
  8132.     long        0x3FFD0000,0xCCECAC08,0xBF04565D,0x00000000
  8133.     long        0x3FFE0000,0xA9C84A47,0xA07F5638,0x00000000
  8134.     long        0x3FFD0000,0xD2420487,0x2DD85160,0x00000000
  8135.     long        0x3FFE0000,0xA80A80A8,0x0A80A80B,0x00000000
  8136.     long        0x3FFD0000,0xD7894992,0x3BC3588A,0x00000000
  8137.     long        0x3FFE0000,0xA655C439,0x2D7B73A8,0x00000000
  8138.     long        0x3FFD0000,0xDCC2C4B4,0x9887DACC,0x00000000
  8139.     long        0x3FFE0000,0xA4A9CF1D,0x96833751,0x00000000
  8140.     long        0x3FFD0000,0xE1EEBD3E,0x6D6A6B9E,0x00000000
  8141.     long        0x3FFE0000,0xA3065E3F,0xAE7CD0E0,0x00000000
  8142.     long        0x3FFD0000,0xE70D785C,0x2F9F5BDC,0x00000000
  8143.     long        0x3FFE0000,0xA16B312E,0xA8FC377D,0x00000000
  8144.     long        0x3FFD0000,0xEC1F392C,0x5179F283,0x00000000
  8145.     long        0x3FFE0000,0x9FD809FD,0x809FD80A,0x00000000
  8146.     long        0x3FFD0000,0xF12440D3,0xE36130E6,0x00000000
  8147.     long        0x3FFE0000,0x9E4CAD23,0xDD5F3A20,0x00000000
  8148.     long        0x3FFD0000,0xF61CCE92,0x346600BB,0x00000000
  8149.     long        0x3FFE0000,0x9CC8E160,0xC3FB19B9,0x00000000
  8150.     long        0x3FFD0000,0xFB091FD3,0x8145630A,0x00000000
  8151.     long        0x3FFE0000,0x9B4C6F9E,0xF03A3CAA,0x00000000
  8152.     long        0x3FFD0000,0xFFE97042,0xBFA4C2AD,0x00000000
  8153.     long        0x3FFE0000,0x99D722DA,0xBDE58F06,0x00000000
  8154.     long        0x3FFE0000,0x825EFCED,0x49369330,0x00000000
  8155.     long        0x3FFE0000,0x9868C809,0x868C8098,0x00000000
  8156.     long        0x3FFE0000,0x84C37A7A,0xB9A905C9,0x00000000
  8157.     long        0x3FFE0000,0x97012E02,0x5C04B809,0x00000000
  8158.     long        0x3FFE0000,0x87224C2E,0x8E645FB7,0x00000000
  8159.     long        0x3FFE0000,0x95A02568,0x095A0257,0x00000000
  8160.     long        0x3FFE0000,0x897B8CAC,0x9F7DE298,0x00000000
  8161.     long        0x3FFE0000,0x94458094,0x45809446,0x00000000
  8162.     long        0x3FFE0000,0x8BCF55DE,0xC4CD05FE,0x00000000
  8163.     long        0x3FFE0000,0x92F11384,0x0497889C,0x00000000
  8164.     long        0x3FFE0000,0x8E1DC0FB,0x89E125E5,0x00000000
  8165.     long        0x3FFE0000,0x91A2B3C4,0xD5E6F809,0x00000000
  8166.     long        0x3FFE0000,0x9066E68C,0x955B6C9B,0x00000000
  8167.     long        0x3FFE0000,0x905A3863,0x3E06C43B,0x00000000
  8168.     long        0x3FFE0000,0x92AADE74,0xC7BE59E0,0x00000000
  8169.     long        0x3FFE0000,0x8F1779D9,0xFDC3A219,0x00000000
  8170.     long        0x3FFE0000,0x94E9BFF6,0x15845643,0x00000000
  8171.     long        0x3FFE0000,0x8DDA5202,0x37694809,0x00000000
  8172.     long        0x3FFE0000,0x9723A1B7,0x20134203,0x00000000
  8173.     long        0x3FFE0000,0x8CA29C04,0x6514E023,0x00000000
  8174.     long        0x3FFE0000,0x995899C8,0x90EB8990,0x00000000
  8175.     long        0x3FFE0000,0x8B70344A,0x139BC75A,0x00000000
  8176.     long        0x3FFE0000,0x9B88BDAA,0x3A3DAE2F,0x00000000
  8177.     long        0x3FFE0000,0x8A42F870,0x5669DB46,0x00000000
  8178.     long        0x3FFE0000,0x9DB4224F,0xFFE1157C,0x00000000
  8179.     long        0x3FFE0000,0x891AC73A,0xE9819B50,0x00000000
  8180.     long        0x3FFE0000,0x9FDADC26,0x8B7A12DA,0x00000000
  8181.     long        0x3FFE0000,0x87F78087,0xF78087F8,0x00000000
  8182.     long        0x3FFE0000,0xA1FCFF17,0xCE733BD4,0x00000000
  8183.     long        0x3FFE0000,0x86D90544,0x7A34ACC6,0x00000000
  8184.     long        0x3FFE0000,0xA41A9E8F,0x5446FB9F,0x00000000
  8185.     long        0x3FFE0000,0x85BF3761,0x2CEE3C9B,0x00000000
  8186.     long        0x3FFE0000,0xA633CD7E,0x6771CD8B,0x00000000
  8187.     long        0x3FFE0000,0x84A9F9C8,0x084A9F9D,0x00000000
  8188.     long        0x3FFE0000,0xA8489E60,0x0B435A5E,0x00000000
  8189.     long        0x3FFE0000,0x83993052,0x3FBE3368,0x00000000
  8190.     long        0x3FFE0000,0xAA59233C,0xCCA4BD49,0x00000000
  8191.     long        0x3FFE0000,0x828CBFBE,0xB9A020A3,0x00000000
  8192.     long        0x3FFE0000,0xAC656DAE,0x6BCC4985,0x00000000
  8193.     long        0x3FFE0000,0x81848DA8,0xFAF0D277,0x00000000
  8194.     long        0x3FFE0000,0xAE6D8EE3,0x60BB2468,0x00000000
  8195.     long        0x3FFE0000,0x80808080,0x80808081,0x00000000
  8196.     long        0x3FFE0000,0xB07197A2,0x3C46C654,0x00000000
  8197.  
  8198.     set        ADJK,L_SCR1
  8199.  
  8200.     set        X,FP_SCR0
  8201.     set        XDCARE,X+2
  8202.     set        XFRAC,X+4
  8203.  
  8204.     set        F,FP_SCR1
  8205.     set        FFRAC,F+4
  8206.  
  8207.     set        KLOG2,FP_SCR0
  8208.  
  8209.     set        SAVEU,FP_SCR0
  8210.  
  8211.     global        slogn
  8212. #--ENTRY POINT FOR LOG(X) FOR X FINITE, NON-ZERO, NOT NAN'S
  8213. slogn:
  8214.     fmov.x        (%a0),%fp0        # LOAD INPUT
  8215.     mov.l        &0x00000000,ADJK(%a6)
  8216.  
  8217. LOGBGN:
  8218. #--FPCR SAVED AND CLEARED, INPUT IS 2^(ADJK)*FP0, FP0 CONTAINS
  8219. #--A FINITE, NON-ZERO, NORMALIZED NUMBER.
  8220.  
  8221.     mov.l        (%a0),%d1
  8222.     mov.w        4(%a0),%d1
  8223.  
  8224.     mov.l        (%a0),X(%a6)
  8225.     mov.l        4(%a0),X+4(%a6)
  8226.     mov.l        8(%a0),X+8(%a6)
  8227.  
  8228.     cmp.l        %d1,&0            # CHECK IF X IS NEGATIVE
  8229.     blt.w        LOGNEG            # LOG OF NEGATIVE ARGUMENT IS INVALID
  8230. # X IS POSITIVE, CHECK IF X IS NEAR 1
  8231.     cmp.l        %d1,&0x3ffef07d     # IS X < 15/16?
  8232.     blt.b        LOGMAIN            # YES
  8233.     cmp.l        %d1,&0x3fff8841     # IS X > 17/16?
  8234.     ble.w        LOGNEAR1        # NO
  8235.  
  8236. LOGMAIN:
  8237. #--THIS SHOULD BE THE USUAL CASE, X NOT VERY CLOSE TO 1
  8238.  
  8239. #--X = 2^(K) * Y, 1 <= Y < 2. THUS, Y = 1.XXXXXXXX....XX IN BINARY.
  8240. #--WE DEFINE F = 1.XXXXXX1, I.E. FIRST 7 BITS OF Y AND ATTACH A 1.
  8241. #--THE IDEA IS THAT LOG(X) = K*LOG2 + LOG(Y)
  8242. #--             = K*LOG2 + LOG(F) + LOG(1 + (Y-F)/F).
  8243. #--NOTE THAT U = (Y-F)/F IS VERY SMALL AND THUS APPROXIMATING
  8244. #--LOG(1+U) CAN BE VERY EFFICIENT.
  8245. #--ALSO NOTE THAT THE VALUE 1/F IS STORED IN A TABLE SO THAT NO
  8246. #--DIVISION IS NEEDED TO CALCULATE (Y-F)/F. 
  8247.  
  8248. #--GET K, Y, F, AND ADDRESS OF 1/F.
  8249.     asr.l        &8,%d1
  8250.     asr.l        &8,%d1            # SHIFTED 16 BITS, BIASED EXPO. OF X
  8251.     sub.l        &0x3FFF,%d1        # THIS IS K
  8252.     add.l        ADJK(%a6),%d1        # ADJUST K, ORIGINAL INPUT MAY BE  DENORM.
  8253.     lea        LOGTBL(%pc),%a0        # BASE ADDRESS OF 1/F AND LOG(F)
  8254.     fmov.l        %d1,%fp1        # CONVERT K TO FLOATING-POINT FORMAT
  8255.  
  8256. #--WHILE THE CONVERSION IS GOING ON, WE GET F AND ADDRESS OF 1/F
  8257.     mov.l        &0x3FFF0000,X(%a6)    # X IS NOW Y, I.E. 2^(-K)*X
  8258.     mov.l        XFRAC(%a6),FFRAC(%a6)
  8259.     and.l        &0xFE000000,FFRAC(%a6)    # FIRST 7 BITS OF Y
  8260.     or.l        &0x01000000,FFRAC(%a6)    # GET F: ATTACH A 1 AT THE EIGHTH BIT
  8261.     mov.l        FFRAC(%a6),%d1    # READY TO GET ADDRESS OF 1/F
  8262.     and.l        &0x7E000000,%d1
  8263.     asr.l        &8,%d1
  8264.     asr.l        &8,%d1
  8265.     asr.l        &4,%d1            # SHIFTED 20, D0 IS THE DISPLACEMENT
  8266.     add.l        %d1,%a0            # A0 IS THE ADDRESS FOR 1/F
  8267.  
  8268.     fmov.x        X(%a6),%fp0
  8269.     mov.l        &0x3fff0000,F(%a6)
  8270.     clr.l        F+8(%a6)
  8271.     fsub.x        F(%a6),%fp0        # Y-F
  8272.     fmovm.x        &0xc,-(%sp)        # SAVE FP2-3 WHILE FP0 IS NOT READY
  8273. #--SUMMARY: FP0 IS Y-F, A0 IS ADDRESS OF 1/F, FP1 IS K
  8274. #--REGISTERS SAVED: FPCR, FP1, FP2
  8275.  
  8276. LP1CONT1:
  8277. #--AN RE-ENTRY POINT FOR LOGNP1
  8278.     fmul.x        (%a0),%fp0        # FP0 IS U = (Y-F)/F
  8279.     fmul.x        LOGOF2(%pc),%fp1    # GET K*LOG2 WHILE FP0 IS NOT READY
  8280.     fmov.x        %fp0,%fp2
  8281.     fmul.x        %fp2,%fp2        # FP2 IS V=U*U
  8282.     fmov.x        %fp1,KLOG2(%a6)        # PUT K*LOG2 IN MEMEORY, FREE FP1
  8283.  
  8284. #--LOG(1+U) IS APPROXIMATED BY
  8285. #--U + V*(A1+U*(A2+U*(A3+U*(A4+U*(A5+U*A6))))) WHICH IS
  8286. #--[U + V*(A1+V*(A3+V*A5))]  +  [U*V*(A2+V*(A4+V*A6))]
  8287.  
  8288.     fmov.x        %fp2,%fp3
  8289.     fmov.x        %fp2,%fp1
  8290.  
  8291.     fmul.d        LOGA6(%pc),%fp1        # V*A6
  8292.     fmul.d        LOGA5(%pc),%fp2        # V*A5
  8293.  
  8294.     fadd.d        LOGA4(%pc),%fp1        # A4+V*A6
  8295.     fadd.d        LOGA3(%pc),%fp2        # A3+V*A5
  8296.  
  8297.     fmul.x        %fp3,%fp1        # V*(A4+V*A6)
  8298.     fmul.x        %fp3,%fp2        # V*(A3+V*A5)
  8299.  
  8300.     fadd.d        LOGA2(%pc),%fp1        # A2+V*(A4+V*A6)
  8301.     fadd.d        LOGA1(%pc),%fp2        # A1+V*(A3+V*A5)
  8302.  
  8303.     fmul.x        %fp3,%fp1        # V*(A2+V*(A4+V*A6))
  8304.     add.l        &16,%a0            # ADDRESS OF LOG(F)
  8305.     fmul.x        %fp3,%fp2        # V*(A1+V*(A3+V*A5))
  8306.  
  8307.     fmul.x        %fp0,%fp1        # U*V*(A2+V*(A4+V*A6))
  8308.     fadd.x        %fp2,%fp0        # U+V*(A1+V*(A3+V*A5))
  8309.  
  8310.     fadd.x        (%a0),%fp1        # LOG(F)+U*V*(A2+V*(A4+V*A6))
  8311.     fmovm.x        (%sp)+,&0x30        # RESTORE FP2-3
  8312.     fadd.x        %fp1,%fp0        # FP0 IS LOG(F) + LOG(1+U)
  8313.  
  8314.     fmov.l        %d0,%fpcr
  8315.     fadd.x        KLOG2(%a6),%fp0        # FINAL ADD
  8316.     bra        t_inx2
  8317.  
  8318.  
  8319. LOGNEAR1:
  8320.  
  8321. # if the input is exactly equal to one, then exit through ld_pzero.
  8322. # if these 2 lines weren't here, the correct answer would be returned
  8323. # but the INEX2 bit would be set.
  8324.     fcmp.b        %fp0,&0x1        # is it equal to one?
  8325.     fbeq.l        ld_pzero        # yes
  8326.  
  8327. #--REGISTERS SAVED: FPCR, FP1. FP0 CONTAINS THE INPUT.
  8328.     fmov.x        %fp0,%fp1
  8329.     fsub.s        one(%pc),%fp1        # FP1 IS X-1
  8330.     fadd.s        one(%pc),%fp0        # FP0 IS X+1
  8331.     fadd.x        %fp1,%fp1        # FP1 IS 2(X-1)
  8332. #--LOG(X) = LOG(1+U/2)-LOG(1-U/2) WHICH IS AN ODD POLYNOMIAL
  8333. #--IN U, U = 2(X-1)/(X+1) = FP1/FP0
  8334.  
  8335. LP1CONT2:
  8336. #--THIS IS AN RE-ENTRY POINT FOR LOGNP1
  8337.     fdiv.x        %fp0,%fp1        # FP1 IS U
  8338.     fmovm.x        &0xc,-(%sp)        # SAVE FP2-3
  8339. #--REGISTERS SAVED ARE NOW FPCR,FP1,FP2,FP3
  8340. #--LET V=U*U, W=V*V, CALCULATE
  8341. #--U + U*V*(B1 + V*(B2 + V*(B3 + V*(B4 + V*B5)))) BY
  8342. #--U + U*V*(  [B1 + W*(B3 + W*B5)]  +  [V*(B2 + W*B4)]  )
  8343.     fmov.x        %fp1,%fp0
  8344.     fmul.x        %fp0,%fp0        # FP0 IS V
  8345.     fmov.x        %fp1,SAVEU(%a6)        # STORE U IN MEMORY, FREE FP1
  8346.     fmov.x        %fp0,%fp1
  8347.     fmul.x        %fp1,%fp1        # FP1 IS W
  8348.  
  8349.     fmov.d        LOGB5(%pc),%fp3
  8350.     fmov.d        LOGB4(%pc),%fp2
  8351.  
  8352.     fmul.x        %fp1,%fp3        # W*B5
  8353.     fmul.x        %fp1,%fp2        # W*B4
  8354.  
  8355.     fadd.d        LOGB3(%pc),%fp3        # B3+W*B5
  8356.     fadd.d        LOGB2(%pc),%fp2        # B2+W*B4
  8357.  
  8358.     fmul.x        %fp3,%fp1        # W*(B3+W*B5), FP3 RELEASED
  8359.  
  8360.     fmul.x        %fp0,%fp2        # V*(B2+W*B4)
  8361.  
  8362.     fadd.d        LOGB1(%pc),%fp1        # B1+W*(B3+W*B5)
  8363.     fmul.x        SAVEU(%a6),%fp0        # FP0 IS U*V
  8364.  
  8365.     fadd.x        %fp2,%fp1        # B1+W*(B3+W*B5) + V*(B2+W*B4), FP2 RELEASED
  8366.     fmovm.x        (%sp)+,&0x30        # FP2-3 RESTORED
  8367.  
  8368.     fmul.x        %fp1,%fp0        # U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )
  8369.  
  8370.     fmov.l        %d0,%fpcr
  8371.     fadd.x        SAVEU(%a6),%fp0
  8372.     bra        t_inx2
  8373.  
  8374. #--REGISTERS SAVED FPCR. LOG(-VE) IS INVALID
  8375. LOGNEG:
  8376.     bra        t_operr
  8377.  
  8378.     global        slognd
  8379. slognd:
  8380. #--ENTRY POINT FOR LOG(X) FOR DENORMALIZED INPUT
  8381.  
  8382.     mov.l        &-100,ADJK(%a6)        # INPUT = 2^(ADJK) * FP0
  8383.  
  8384. #----normalize the input value by left shifting k bits (k to be determined
  8385. #----below), adjusting exponent and storing -k to  ADJK
  8386. #----the value TWOTO100 is no longer needed.
  8387. #----Note that this code assumes the denormalized input is NON-ZERO.
  8388.  
  8389.     movm.l        &0x3f00,-(%sp)        # save some registers  {d2-d7}
  8390.     mov.l        (%a0),%d3        # D3 is exponent of smallest norm. #
  8391.     mov.l        4(%a0),%d4
  8392.     mov.l        8(%a0),%d5        # (D4,D5) is (Hi_X,Lo_X)
  8393.     clr.l        %d2            # D2 used for holding K
  8394.  
  8395.     tst.l        %d4
  8396.     bne.b        Hi_not0
  8397.  
  8398. Hi_0:
  8399.     mov.l        %d5,%d4
  8400.     clr.l        %d5
  8401.     mov.l        &32,%d2
  8402.     clr.l        %d6
  8403.     bfffo        %d4{&0:&32},%d6
  8404.     lsl.l        %d6,%d4
  8405.     add.l        %d6,%d2            # (D3,D4,D5) is normalized
  8406.  
  8407.     mov.l        %d3,X(%a6)
  8408.     mov.l        %d4,XFRAC(%a6)
  8409.     mov.l        %d5,XFRAC+4(%a6)
  8410.     neg.l        %d2
  8411.     mov.l        %d2,ADJK(%a6)
  8412.     fmov.x        X(%a6),%fp0
  8413.     movm.l        (%sp)+,&0xfc        # restore registers {d2-d7}
  8414.     lea        X(%a6),%a0
  8415.     bra.w        LOGBGN            # begin regular log(X)
  8416.  
  8417. Hi_not0:
  8418.     clr.l        %d6
  8419.     bfffo        %d4{&0:&32},%d6        # find first 1
  8420.     mov.l        %d6,%d2            # get k
  8421.     lsl.l        %d6,%d4
  8422.     mov.l        %d5,%d7            # a copy of D5
  8423.     lsl.l        %d6,%d5
  8424.     neg.l        %d6
  8425.     add.l        &32,%d6
  8426.     lsr.l        %d6,%d7
  8427.     or.l        %d7,%d4            # (D3,D4,D5) normalized
  8428.  
  8429.     mov.l        %d3,X(%a6)
  8430.     mov.l        %d4,XFRAC(%a6)
  8431.     mov.l        %d5,XFRAC+4(%a6)
  8432.     neg.l        %d2
  8433.     mov.l        %d2,ADJK(%a6)
  8434.     fmov.x        X(%a6),%fp0
  8435.     movm.l        (%sp)+,&0xfc        # restore registers {d2-d7}
  8436.     lea        X(%a6),%a0
  8437.     bra.w        LOGBGN            # begin regular log(X)
  8438.  
  8439.     global        slognp1
  8440. #--ENTRY POINT FOR LOG(1+X) FOR X FINITE, NON-ZERO, NOT NAN'S
  8441. slognp1:
  8442.     fmov.x        (%a0),%fp0        # LOAD INPUT
  8443.     fabs.x        %fp0            # test magnitude
  8444.     fcmp.x        %fp0,LTHOLD(%pc)    # compare with min threshold
  8445.     fbgt.w        LP1REAL            # if greater, continue
  8446.     fmov.l        %d0,%fpcr
  8447.     mov.b        &FMOV_OP,%d1        # last inst is MOVE
  8448.     fmov.x        (%a0),%fp0        # return signed argument
  8449.     bra        t_catch
  8450.  
  8451. LP1REAL:
  8452.     fmov.x        (%a0),%fp0        # LOAD INPUT
  8453.     mov.l        &0x00000000,ADJK(%a6)
  8454.     fmov.x        %fp0,%fp1        # FP1 IS INPUT Z
  8455.     fadd.s        one(%pc),%fp0        # X := ROUND(1+Z)
  8456.     fmov.x        %fp0,X(%a6)
  8457.     mov.w        XFRAC(%a6),XDCARE(%a6)
  8458.     mov.l        X(%a6),%d1
  8459.     cmp.l        %d1,&0
  8460.     ble.w        LP1NEG0            # LOG OF ZERO OR -VE
  8461.     cmp.l        %d1,&0x3ffe8000     # IS BOUNDS [1/2,3/2]?
  8462.     blt.w        LOGMAIN
  8463.     cmp.l        %d1,&0x3fffc000
  8464.     bgt.w        LOGMAIN 
  8465. #--IF 1+Z > 3/2 OR 1+Z < 1/2, THEN X, WHICH IS ROUNDING 1+Z,
  8466. #--CONTAINS AT LEAST 63 BITS OF INFORMATION OF Z. IN THAT CASE,
  8467. #--SIMPLY INVOKE LOG(X) FOR LOG(1+Z).
  8468.  
  8469. LP1NEAR1:
  8470. #--NEXT SEE IF EXP(-1/16) < X < EXP(1/16)
  8471.     cmp.l        %d1,&0x3ffef07d
  8472.     blt.w        LP1CARE
  8473.     cmp.l        %d1,&0x3fff8841
  8474.     bgt.w        LP1CARE
  8475.  
  8476. LP1ONE16:
  8477. #--EXP(-1/16) < X < EXP(1/16). LOG(1+Z) = LOG(1+U/2) - LOG(1-U/2)
  8478. #--WHERE U = 2Z/(2+Z) = 2Z/(1+X).
  8479.     fadd.x        %fp1,%fp1        # FP1 IS 2Z
  8480.     fadd.s        one(%pc),%fp0        # FP0 IS 1+X
  8481. #--U = FP1/FP0
  8482.     bra.w        LP1CONT2
  8483.  
  8484. LP1CARE:
  8485. #--HERE WE USE THE USUAL TABLE DRIVEN APPROACH. CARE HAS TO BE
  8486. #--TAKEN BECAUSE 1+Z CAN HAVE 67 BITS OF INFORMATION AND WE MUST
  8487. #--PRESERVE ALL THE INFORMATION. BECAUSE 1+Z IS IN [1/2,3/2],
  8488. #--THERE ARE ONLY TWO CASES.
  8489. #--CASE 1: 1+Z < 1, THEN K = -1 AND Y-F = (2-F) + 2Z
  8490. #--CASE 2: 1+Z > 1, THEN K = 0  AND Y-F = (1-F) + Z
  8491. #--ON RETURNING TO LP1CONT1, WE MUST HAVE K IN FP1, ADDRESS OF
  8492. #--(1/F) IN A0, Y-F IN FP0, AND FP2 SAVED.
  8493.  
  8494.     mov.l        XFRAC(%a6),FFRAC(%a6)
  8495.     and.l        &0xFE000000,FFRAC(%a6)
  8496.     or.l        &0x01000000,FFRAC(%a6)    # F OBTAINED
  8497.     cmp.l        %d1,&0x3FFF8000        # SEE IF 1+Z > 1
  8498.     bge.b        KISZERO
  8499.  
  8500. KISNEG1:
  8501.     fmov.s        TWO(%pc),%fp0
  8502.     mov.l        &0x3fff0000,F(%a6)
  8503.     clr.l        F+8(%a6)
  8504.     fsub.x        F(%a6),%fp0        # 2-F
  8505.     mov.l        FFRAC(%a6),%d1
  8506.     and.l        &0x7E000000,%d1
  8507.     asr.l        &8,%d1
  8508.     asr.l        &8,%d1
  8509.     asr.l        &4,%d1            # D0 CONTAINS DISPLACEMENT FOR 1/F
  8510.     fadd.x        %fp1,%fp1        # GET 2Z
  8511.     fmovm.x        &0xc,-(%sp)        # SAVE FP2  {%fp2/%fp3}
  8512.     fadd.x        %fp1,%fp0        # FP0 IS Y-F = (2-F)+2Z
  8513.     lea        LOGTBL(%pc),%a0        # A0 IS ADDRESS OF 1/F
  8514.     add.l        %d1,%a0
  8515.     fmov.s        negone(%pc),%fp1    # FP1 IS K = -1
  8516.     bra.w        LP1CONT1
  8517.  
  8518. KISZERO:
  8519.     fmov.s        one(%pc),%fp0
  8520.     mov.l        &0x3fff0000,F(%a6)
  8521.     clr.l        F+8(%a6)
  8522.     fsub.x        F(%a6),%fp0        # 1-F
  8523.     mov.l        FFRAC(%a6),%d1
  8524.     and.l        &0x7E000000,%d1
  8525.     asr.l        &8,%d1
  8526.     asr.l        &8,%d1
  8527.     asr.l        &4,%d1
  8528.     fadd.x        %fp1,%fp0        # FP0 IS Y-F
  8529.     fmovm.x        &0xc,-(%sp)        # FP2 SAVED {%fp2/%fp3}
  8530.     lea        LOGTBL(%pc),%a0
  8531.     add.l        %d1,%a0            # A0 IS ADDRESS OF 1/F
  8532.     fmov.s        zero(%pc),%fp1        # FP1 IS K = 0
  8533.     bra.w        LP1CONT1
  8534.  
  8535. LP1NEG0:
  8536. #--FPCR SAVED. D0 IS X IN COMPACT FORM.
  8537.     cmp.l        %d1,&0
  8538.     blt.b        LP1NEG
  8539. LP1ZERO:
  8540.     fmov.s        negone(%pc),%fp0
  8541.  
  8542.     fmov.l        %d0,%fpcr
  8543.     bra        t_dz
  8544.  
  8545. LP1NEG:
  8546.     fmov.s        zero(%pc),%fp0
  8547.  
  8548.     fmov.l        %d0,%fpcr
  8549.     bra        t_operr
  8550.  
  8551.     global        slognp1d
  8552. #--ENTRY POINT FOR LOG(1+Z) FOR DENORMALIZED INPUT
  8553. # Simply return the denorm
  8554. slognp1d:
  8555.     bra        t_extdnrm
  8556.  
  8557. #########################################################################
  8558. # satanh():  computes the inverse hyperbolic tangent of a norm input    #
  8559. # satanhd(): computes the inverse hyperbolic tangent of a denorm input    #
  8560. #                                    #
  8561. # INPUT ***************************************************************    #
  8562. #    a0 = pointer to extended precision input            #
  8563. #    d0 = round precision,mode                    #
  8564. #                                    #
  8565. # OUTPUT **************************************************************    # 
  8566. #    fp0 = arctanh(X)                        #
  8567. #                                    #
  8568. # ACCURACY and MONOTONICITY *******************************************    #
  8569. #    The returned result is within 3 ulps in    64 significant bit,    #
  8570. #    i.e. within 0.5001 ulp to 53 bits if the result is subsequently    #
  8571. #    rounded to double precision. The result is provably monotonic    #
  8572. #    in double precision.                        #
  8573. #                                    #
  8574. # ALGORITHM ***********************************************************    #
  8575. #                                    #
  8576. #    ATANH                                #
  8577. #    1. If |X| >= 1, go to 3.                    #
  8578. #                                    #
  8579. #    2. (|X| < 1) Calculate atanh(X) by                #
  8580. #        sgn := sign(X)                        #
  8581. #        y := |X|                        #
  8582. #        z := 2y/(1-y)                        #
  8583. #        atanh(X) := sgn * (1/2) * logp1(z)            #
  8584. #        Exit.                            #
  8585. #                                    #
  8586. #    3. If |X| > 1, go to 5.                        #
  8587. #                                    #
  8588. #    4. (|X| = 1) Generate infinity with an appropriate sign and    #
  8589. #        divide-by-zero by                    #
  8590. #        sgn := sign(X)                        #
  8591. #        atan(X) := sgn / (+0).                    #
  8592. #        Exit.                            #
  8593. #                                    #
  8594. #    5. (|X| > 1) Generate an invalid operation by 0 * infinity.    #
  8595. #        Exit.                            #
  8596. #                                    #
  8597. #########################################################################
  8598.  
  8599.     global        satanh
  8600. satanh:
  8601.     mov.l        (%a0),%d1
  8602.     mov.w        4(%a0),%d1
  8603.     and.l        &0x7FFFFFFF,%d1
  8604.     cmp.l        %d1,&0x3FFF8000
  8605.     bge.b        ATANHBIG
  8606.  
  8607. #--THIS IS THE USUAL CASE, |X| < 1
  8608. #--Y = |X|, Z = 2Y/(1-Y), ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z).
  8609.  
  8610.     fabs.x        (%a0),%fp0        # Y = |X|
  8611.     fmov.x        %fp0,%fp1
  8612.     fneg.x        %fp1            # -Y
  8613.     fadd.x        %fp0,%fp0        # 2Y
  8614.     fadd.s        &0x3F800000,%fp1    # 1-Y
  8615.     fdiv.x        %fp1,%fp0        # 2Y/(1-Y)
  8616.     mov.l        (%a0),%d1
  8617.     and.l        &0x80000000,%d1
  8618.     or.l        &0x3F000000,%d1        # SIGN(X)*HALF
  8619.     mov.l        %d1,-(%sp)
  8620.  
  8621.     mov.l        %d0,-(%sp)        # save rnd prec,mode
  8622.     clr.l        %d0            # pass ext prec,RN
  8623.     fmovm.x        &0x01,-(%sp)        # save Z on stack
  8624.     lea        (%sp),%a0        # pass ptr to Z
  8625.     bsr        slognp1            # LOG1P(Z)
  8626.     add.l        &0xc,%sp        # clear Z from stack
  8627.  
  8628.     mov.l        (%sp)+,%d0        # fetch old prec,mode
  8629.     fmov.l        %d0,%fpcr        # load it
  8630.     mov.b        &FMUL_OP,%d1        # last inst is MUL
  8631.     fmul.s        (%sp)+,%fp0
  8632.     bra        t_catch
  8633.  
  8634. ATANHBIG:
  8635.     fabs.x        (%a0),%fp0        # |X|
  8636.     fcmp.s        %fp0,&0x3F800000
  8637.     fbgt        t_operr
  8638.     bra        t_dz
  8639.  
  8640.     global        satanhd
  8641. #--ATANH(X) = X FOR DENORMALIZED X
  8642. satanhd:
  8643.     bra        t_extdnrm
  8644.  
  8645. #########################################################################
  8646. # slog10():  computes the base-10 logarithm of a normalized input    #
  8647. # slog10d(): computes the base-10 logarithm of a denormalized input    #
  8648. # slog2():   computes the base-2 logarithm of a normalized input    #
  8649. # slog2d():  computes the base-2 logarithm of a denormalized input    #
  8650. #                                    #
  8651. # INPUT *************************************************************** #
  8652. #    a0 = pointer to extended precision input            #
  8653. #    d0 = round precision,mode                    #
  8654. #                                    #
  8655. # OUTPUT **************************************************************    #
  8656. #    fp0 = log_10(X) or log_2(X)                    #
  8657. #                                    #
  8658. # ACCURACY and MONOTONICITY *******************************************    #
  8659. #    The returned result is within 1.7 ulps in 64 significant bit,    #
  8660. #    i.e. within 0.5003 ulp to 53 bits if the result is subsequently    #
  8661. #    rounded to double precision. The result is provably monotonic    #
  8662. #    in double precision.                        #
  8663. #                                    #
  8664. # ALGORITHM ***********************************************************    #
  8665. #                                    #
  8666. #       slog10d:                            #
  8667. #                                    #
  8668. #       Step 0.    If X < 0, create a NaN and raise the invalid operation    #
  8669. #               flag. Otherwise, save FPCR in D1; set FpCR to default.    #
  8670. #       Notes:  Default means round-to-nearest mode, no floating-point    #
  8671. #               traps, and precision control = double extended.        #
  8672. #                                    #
  8673. #       Step 1. Call slognd to obtain Y = log(X), the natural log of X.    #
  8674. #       Notes:  Even if X is denormalized, log(X) is always normalized.    #
  8675. #                                    #
  8676. #       Step 2.  Compute log_10(X) = log(X) * (1/log(10)).        #
  8677. #            2.1 Restore the user FPCR                    #
  8678. #            2.2 Return ans := Y * INV_L10.                #
  8679. #                                    #
  8680. #       slog10:                             #
  8681. #                                    #
  8682. #       Step 0. If X < 0, create a NaN and raise the invalid operation    #
  8683. #               flag. Otherwise, save FPCR in D1; set FpCR to default.    #
  8684. #       Notes:  Default means round-to-nearest mode, no floating-point    #
  8685. #               traps, and precision control = double extended.        #
  8686. #                                    #
  8687. #       Step 1. Call sLogN to obtain Y = log(X), the natural log of X.    #
  8688. #                                    #
  8689. #       Step 2.   Compute log_10(X) = log(X) * (1/log(10)).        #
  8690. #            2.1  Restore the user FPCR                    #
  8691. #            2.2  Return ans := Y * INV_L10.                #
  8692. #                                    #
  8693. #       sLog2d:                                #
  8694. #                                    #
  8695. #       Step 0. If X < 0, create a NaN and raise the invalid operation    #
  8696. #               flag. Otherwise, save FPCR in D1; set FpCR to default.    #
  8697. #       Notes:  Default means round-to-nearest mode, no floating-point    #
  8698. #               traps, and precision control = double extended.        #
  8699. #                                    #
  8700. #       Step 1. Call slognd to obtain Y = log(X), the natural log of X.    #
  8701. #       Notes:  Even if X is denormalized, log(X) is always normalized.    #
  8702. #                                    #
  8703. #       Step 2.   Compute log_10(X) = log(X) * (1/log(2)).        #
  8704. #            2.1  Restore the user FPCR                    #
  8705. #            2.2  Return ans := Y * INV_L2.                #
  8706. #                                    #
  8707. #       sLog2:                                #
  8708. #                                    #
  8709. #       Step 0. If X < 0, create a NaN and raise the invalid operation    #
  8710. #               flag. Otherwise, save FPCR in D1; set FpCR to default.    #
  8711. #       Notes:  Default means round-to-nearest mode, no floating-point    #
  8712. #               traps, and precision control = double extended.        #
  8713. #                                    #
  8714. #       Step 1. If X is not an integer power of two, i.e., X != 2^k,    #
  8715. #               go to Step 3.                        #
  8716. #                                    #
  8717. #       Step 2.   Return k.                        #
  8718. #            2.1  Get integer k, X = 2^k.                #
  8719. #            2.2  Restore the user FPCR.                #
  8720. #            2.3  Return ans := convert-to-double-extended(k).        #
  8721. #                                    #
  8722. #       Step 3. Call sLogN to obtain Y = log(X), the natural log of X.    #
  8723. #                                    #
  8724. #       Step 4.   Compute log_2(X) = log(X) * (1/log(2)).        #
  8725. #            4.1  Restore the user FPCR                    #
  8726. #            4.2  Return ans := Y * INV_L2.                #
  8727. #                                    #
  8728. #########################################################################
  8729.  
  8730. INV_L10:
  8731.     long        0x3FFD0000,0xDE5BD8A9,0x37287195,0x00000000
  8732.  
  8733. INV_L2:
  8734.     long        0x3FFF0000,0xB8AA3B29,0x5C17F0BC,0x00000000
  8735.  
  8736.     global        slog10
  8737. #--entry point for Log10(X), X is normalized
  8738. slog10:
  8739.     fmov.b        &0x1,%fp0
  8740.     fcmp.x        %fp0,(%a0)        # if operand == 1,
  8741.     fbeq.l        ld_pzero        # return an EXACT zero
  8742.  
  8743.     mov.l        (%a0),%d1
  8744.     blt.w        invalid
  8745.     mov.l        %d0,-(%sp)
  8746.     clr.l        %d0
  8747.     bsr        slogn            # log(X), X normal.
  8748.     fmov.l        (%sp)+,%fpcr
  8749.     fmul.x        INV_L10(%pc),%fp0
  8750.     bra        t_inx2
  8751.  
  8752.     global        slog10d
  8753. #--entry point for Log10(X), X is denormalized
  8754. slog10d:
  8755.     mov.l        (%a0),%d1
  8756.     blt.w        invalid
  8757.     mov.l        %d0,-(%sp)
  8758.     clr.l        %d0
  8759.     bsr        slognd            # log(X), X denorm.
  8760.     fmov.l        (%sp)+,%fpcr
  8761.     fmul.x        INV_L10(%pc),%fp0
  8762.     bra        t_minx2
  8763.  
  8764.     global        slog2
  8765. #--entry point for Log2(X), X is normalized
  8766. slog2:
  8767.     mov.l        (%a0),%d1
  8768.     blt.w        invalid
  8769.  
  8770.     mov.l        8(%a0),%d1
  8771.     bne.b        continue        # X is not 2^k
  8772.  
  8773.     mov.l        4(%a0),%d1
  8774.     and.l        &0x7FFFFFFF,%d1
  8775.     bne.b        continue
  8776.  
  8777. #--X = 2^k.
  8778.     mov.w        (%a0),%d1
  8779.     and.l        &0x00007FFF,%d1
  8780.     sub.l        &0x3FFF,%d1
  8781.     beq.l        ld_pzero
  8782.     fmov.l        %d0,%fpcr
  8783.     fmov.l        %d1,%fp0
  8784.     bra        t_inx2
  8785.  
  8786. continue:
  8787.     mov.l        %d0,-(%sp)
  8788.     clr.l        %d0
  8789.     bsr        slogn            # log(X), X normal.
  8790.     fmov.l        (%sp)+,%fpcr
  8791.     fmul.x        INV_L2(%pc),%fp0
  8792.     bra        t_inx2
  8793.  
  8794. invalid:
  8795.     bra        t_operr
  8796.  
  8797.     global        slog2d
  8798. #--entry point for Log2(X), X is denormalized
  8799. slog2d:
  8800.     mov.l        (%a0),%d1
  8801.     blt.w        invalid
  8802.     mov.l        %d0,-(%sp)
  8803.     clr.l        %d0
  8804.     bsr        slognd            # log(X), X denorm.
  8805.     fmov.l        (%sp)+,%fpcr
  8806.     fmul.x        INV_L2(%pc),%fp0
  8807.     bra        t_minx2
  8808.  
  8809. #########################################################################
  8810. # stwotox():  computes 2**X for a normalized input            #
  8811. # stwotoxd(): computes 2**X for a denormalized input            #
  8812. # stentox():  computes 10**X for a normalized input            #
  8813. # stentoxd(): computes 10**X for a denormalized input            #
  8814. #                                    #
  8815. # INPUT ***************************************************************    #
  8816. #    a0 = pointer to extended precision input            #
  8817. #    d0 = round precision,mode                    #
  8818. #                                    #
  8819. # OUTPUT **************************************************************    #
  8820. #    fp0 = 2**X or 10**X                        #
  8821. #                                    #
  8822. # ACCURACY and MONOTONICITY *******************************************    #
  8823. #    The returned result is within 2 ulps in 64 significant bit,     #
  8824. #    i.e. within 0.5001 ulp to 53 bits if the result is subsequently    #
  8825. #    rounded to double precision. The result is provably monotonic    #
  8826. #    in double precision.                        #
  8827. #                                    #
  8828. # ALGORITHM ***********************************************************    #
  8829. #                                    #
  8830. #    twotox                                #
  8831. #    1. If |X| > 16480, go to ExpBig.                #
  8832. #                                    #
  8833. #    2. If |X| < 2**(-70), go to ExpSm.                #
  8834. #                                    #
  8835. #    3. Decompose X as X = N/64 + r where |r| <= 1/128. Furthermore    #
  8836. #        decompose N as                        #
  8837. #         N = 64(M + M') + j,  j = 0,1,2,...,63.            #
  8838. #                                    #
  8839. #    4. Overwrite r := r * log2. Then                #
  8840. #        2**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r).        #
  8841. #        Go to expr to compute that expression.            #
  8842. #                                    #
  8843. #    tentox                                #
  8844. #    1. If |X| > 16480*log_10(2) (base 10 log of 2), go to ExpBig.    #
  8845. #                                    #
  8846. #    2. If |X| < 2**(-70), go to ExpSm.                #
  8847. #                                    #
  8848. #    3. Set y := X*log_2(10)*64 (base 2 log of 10). Set        #
  8849. #        N := round-to-int(y). Decompose N as            #
  8850. #         N = 64(M + M') + j,  j = 0,1,2,...,63.            #
  8851. #                                    #
  8852. #    4. Define r as                            #
  8853. #        r := ((X - N*L1)-N*L2) * L10                #
  8854. #        where L1, L2 are the leading and trailing parts of     #
  8855. #        log_10(2)/64 and L10 is the natural log of 10. Then    #
  8856. #        10**X = 2**(M') * 2**(M) * 2**(j/64) * exp(r).        #
  8857. #        Go to expr to compute that expression.            #
  8858. #                                    #
  8859. #    expr                                #
  8860. #    1. Fetch 2**(j/64) from table as Fact1 and Fact2.        #
  8861. #                                    #
  8862. #    2. Overwrite Fact1 and Fact2 by                    #
  8863. #        Fact1 := 2**(M) * Fact1                    #
  8864. #        Fact2 := 2**(M) * Fact2                    #
  8865. #        Thus Fact1 + Fact2 = 2**(M) * 2**(j/64).        #
  8866. #                                    #
  8867. #    3. Calculate P where 1 + P approximates exp(r):            #
  8868. #        P = r + r*r*(A1+r*(A2+...+r*A5)).            #
  8869. #                                    #
  8870. #    4. Let AdjFact := 2**(M'). Return                #
  8871. #        AdjFact * ( Fact1 + ((Fact1*P) + Fact2) ).        #
  8872. #        Exit.                            #
  8873. #                                    #
  8874. #    ExpBig                                #
  8875. #    1. Generate overflow by Huge * Huge if X > 0; otherwise,     #
  8876. #            generate underflow by Tiny * Tiny.            #
  8877. #                                    #
  8878. #    ExpSm                                #
  8879. #    1. Return 1 + X.                        #
  8880. #                                    #
  8881. #########################################################################
  8882.  
  8883. L2TEN64:
  8884.     long        0x406A934F,0x0979A371    # 64LOG10/LOG2
  8885. L10TWO1:
  8886.     long        0x3F734413,0x509F8000    # LOG2/64LOG10
  8887.  
  8888. L10TWO2:
  8889.     long        0xBFCD0000,0xC0219DC1,0xDA994FD2,0x00000000
  8890.  
  8891. LOG10:    long        0x40000000,0x935D8DDD,0xAAA8AC17,0x00000000
  8892.  
  8893. LOG2:    long        0x3FFE0000,0xB17217F7,0xD1CF79AC,0x00000000
  8894.  
  8895. EXPA5:    long        0x3F56C16D,0x6F7BD0B2
  8896. EXPA4:    long        0x3F811112,0x302C712C
  8897. EXPA3:    long        0x3FA55555,0x55554CC1
  8898. EXPA2:    long        0x3FC55555,0x55554A54
  8899. EXPA1:    long        0x3FE00000,0x00000000,0x00000000,0x00000000
  8900.  
  8901. TEXPTBL:
  8902.     long        0x3FFF0000,0x80000000,0x00000000,0x3F738000
  8903.     long        0x3FFF0000,0x8164D1F3,0xBC030773,0x3FBEF7CA
  8904.     long        0x3FFF0000,0x82CD8698,0xAC2BA1D7,0x3FBDF8A9
  8905.     long        0x3FFF0000,0x843A28C3,0xACDE4046,0x3FBCD7C9
  8906.     long        0x3FFF0000,0x85AAC367,0xCC487B15,0xBFBDE8DA
  8907.     long        0x3FFF0000,0x871F6196,0x9E8D1010,0x3FBDE85C
  8908.     long        0x3FFF0000,0x88980E80,0x92DA8527,0x3FBEBBF1
  8909.     long        0x3FFF0000,0x8A14D575,0x496EFD9A,0x3FBB80CA
  8910.     long        0x3FFF0000,0x8B95C1E3,0xEA8BD6E7,0xBFBA8373
  8911.     long        0x3FFF0000,0x8D1ADF5B,0x7E5BA9E6,0xBFBE9670
  8912.     long        0x3FFF0000,0x8EA4398B,0x45CD53C0,0x3FBDB700
  8913.     long        0x3FFF0000,0x9031DC43,0x1466B1DC,0x3FBEEEB0
  8914.     long        0x3FFF0000,0x91C3D373,0xAB11C336,0x3FBBFD6D
  8915.     long        0x3FFF0000,0x935A2B2F,0x13E6E92C,0xBFBDB319
  8916.     long        0x3FFF0000,0x94F4EFA8,0xFEF70961,0x3FBDBA2B
  8917.     long        0x3FFF0000,0x96942D37,0x20185A00,0x3FBE91D5
  8918.     long        0x3FFF0000,0x9837F051,0x8DB8A96F,0x3FBE8D5A
  8919.     long        0x3FFF0000,0x99E04593,0x20B7FA65,0xBFBCDE7B
  8920.     long        0x3FFF0000,0x9B8D39B9,0xD54E5539,0xBFBEBAAF
  8921.     long        0x3FFF0000,0x9D3ED9A7,0x2CFFB751,0xBFBD86DA
  8922.     long        0x3FFF0000,0x9EF53260,0x91A111AE,0xBFBEBEDD
  8923.     long        0x3FFF0000,0xA0B0510F,0xB9714FC2,0x3FBCC96E
  8924.     long        0x3FFF0000,0xA2704303,0x0C496819,0xBFBEC90B
  8925.     long        0x3FFF0000,0xA43515AE,0x09E6809E,0x3FBBD1DB
  8926.     long        0x3FFF0000,0xA5FED6A9,0xB15138EA,0x3FBCE5EB
  8927.     long        0x3FFF0000,0xA7CD93B4,0xE965356A,0xBFBEC274
  8928.     long        0x3FFF0000,0xA9A15AB4,0xEA7C0EF8,0x3FBEA83C
  8929.     long        0x3FFF0000,0xAB7A39B5,0xA93ED337,0x3FBECB00
  8930.     long        0x3FFF0000,0xAD583EEA,0x42A14AC6,0x3FBE9301
  8931.     long        0x3FFF0000,0xAF3B78AD,0x690A4375,0xBFBD8367
  8932.     long        0x3FFF0000,0xB123F581,0xD2AC2590,0xBFBEF05F
  8933.     long        0x3FFF0000,0xB311C412,0xA9112489,0x3FBDFB3C
  8934.     long        0x3FFF0000,0xB504F333,0xF9DE6484,0x3FBEB2FB
  8935.     long        0x3FFF0000,0xB6FD91E3,0x28D17791,0x3FBAE2CB
  8936.     long        0x3FFF0000,0xB8FBAF47,0x62FB9EE9,0x3FBCDC3C
  8937.     long        0x3FFF0000,0xBAFF5AB2,0x133E45FB,0x3FBEE9AA
  8938.     long        0x3FFF0000,0xBD08A39F,0x580C36BF,0xBFBEAEFD
  8939.     long        0x3FFF0000,0xBF1799B6,0x7A731083,0xBFBCBF51
  8940.     long        0x3FFF0000,0xC12C4CCA,0x66709456,0x3FBEF88A
  8941.     long        0x3FFF0000,0xC346CCDA,0x24976407,0x3FBD83B2
  8942.     long        0x3FFF0000,0xC5672A11,0x5506DADD,0x3FBDF8AB
  8943.     long        0x3FFF0000,0xC78D74C8,0xABB9B15D,0xBFBDFB17
  8944.     long        0x3FFF0000,0xC9B9BD86,0x6E2F27A3,0xBFBEFE3C
  8945.     long        0x3FFF0000,0xCBEC14FE,0xF2727C5D,0xBFBBB6F8
  8946.     long        0x3FFF0000,0xCE248C15,0x1F8480E4,0xBFBCEE53
  8947.     long        0x3FFF0000,0xD06333DA,0xEF2B2595,0xBFBDA4AE
  8948.     long        0x3FFF0000,0xD2A81D91,0xF12AE45A,0x3FBC9124
  8949.     long        0x3FFF0000,0xD4F35AAB,0xCFEDFA1F,0x3FBEB243
  8950.     long        0x3FFF0000,0xD744FCCA,0xD69D6AF4,0x3FBDE69A
  8951.     long        0x3FFF0000,0xD99D15C2,0x78AFD7B6,0xBFB8BC61
  8952.     long        0x3FFF0000,0xDBFBB797,0xDAF23755,0x3FBDF610
  8953.     long        0x3FFF0000,0xDE60F482,0x5E0E9124,0xBFBD8BE1
  8954.     long        0x3FFF0000,0xE0CCDEEC,0x2A94E111,0x3FBACB12
  8955.     long        0x3FFF0000,0xE33F8972,0xBE8A5A51,0x3FBB9BFE
  8956.     long        0x3FFF0000,0xE5B906E7,0x7C8348A8,0x3FBCF2F4
  8957.     long        0x3FFF0000,0xE8396A50,0x3C4BDC68,0x3FBEF22F
  8958.     long        0x3FFF0000,0xEAC0C6E7,0xDD24392F,0xBFBDBF4A
  8959.     long        0x3FFF0000,0xED4F301E,0xD9942B84,0x3FBEC01A
  8960.     long        0x3FFF0000,0xEFE4B99B,0xDCDAF5CB,0x3FBE8CAC
  8961.     long        0x3FFF0000,0xF281773C,0x59FFB13A,0xBFBCBB3F
  8962.     long        0x3FFF0000,0xF5257D15,0x2486CC2C,0x3FBEF73A
  8963.     long        0x3FFF0000,0xF7D0DF73,0x0AD13BB9,0xBFB8B795
  8964.     long        0x3FFF0000,0xFA83B2DB,0x722A033A,0x3FBEF84B
  8965.     long        0x3FFF0000,0xFD3E0C0C,0xF486C175,0xBFBEF581
  8966.  
  8967.     set        INT,L_SCR1
  8968.  
  8969.     set        X,FP_SCR0
  8970.     set        XDCARE,X+2
  8971.     set        XFRAC,X+4
  8972.  
  8973.     set        ADJFACT,FP_SCR0
  8974.  
  8975.     set        FACT1,FP_SCR0
  8976.     set        FACT1HI,FACT1+4
  8977.     set        FACT1LOW,FACT1+8
  8978.  
  8979.     set        FACT2,FP_SCR1
  8980.     set        FACT2HI,FACT2+4
  8981.     set        FACT2LOW,FACT2+8
  8982.  
  8983.     global        stwotox
  8984. #--ENTRY POINT FOR 2**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
  8985. stwotox:
  8986.     fmovm.x        (%a0),&0x80        # LOAD INPUT
  8987.  
  8988.     mov.l        (%a0),%d1
  8989.     mov.w        4(%a0),%d1
  8990.     fmov.x        %fp0,X(%a6)
  8991.     and.l        &0x7FFFFFFF,%d1
  8992.  
  8993.     cmp.l        %d1,&0x3FB98000        # |X| >= 2**(-70)?
  8994.     bge.b        TWOOK1
  8995.     bra.w        EXPBORS
  8996.  
  8997. TWOOK1:
  8998.     cmp.l        %d1,&0x400D80C0        # |X| > 16480?
  8999.     ble.b        TWOMAIN
  9000.     bra.w        EXPBORS
  9001.  
  9002. TWOMAIN:
  9003. #--USUAL CASE, 2^(-70) <= |X| <= 16480
  9004.  
  9005.     fmov.x        %fp0,%fp1
  9006.     fmul.s        &0x42800000,%fp1    # 64 * X
  9007.     fmov.l        %fp1,INT(%a6)        # N = ROUND-TO-INT(64 X)
  9008.     mov.l        %d2,-(%sp)
  9009.     lea        TEXPTBL(%pc),%a1    # LOAD ADDRESS OF TABLE OF 2^(J/64)
  9010.     fmov.l        INT(%a6),%fp1        # N --> FLOATING FMT
  9011.     mov.l        INT(%a6),%d1
  9012.     mov.l        %d1,%d2
  9013.     and.l        &0x3F,%d1        # D0 IS J
  9014.     asl.l        &4,%d1            # DISPLACEMENT FOR 2^(J/64)
  9015.     add.l        %d1,%a1            # ADDRESS FOR 2^(J/64)
  9016.     asr.l        &6,%d2            # d2 IS L, N = 64L + J
  9017.     mov.l        %d2,%d1
  9018.     asr.l        &1,%d1            # D0 IS M
  9019.     sub.l        %d1,%d2            # d2 IS M', N = 64(M+M') + J
  9020.     add.l        &0x3FFF,%d2
  9021.  
  9022. #--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
  9023. #--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
  9024. #--ADJFACT = 2^(M').
  9025. #--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
  9026.  
  9027.     fmovm.x        &0x0c,-(%sp)        # save fp2/fp3
  9028.  
  9029.     fmul.s        &0x3C800000,%fp1    # (1/64)*N
  9030.     mov.l        (%a1)+,FACT1(%a6)
  9031.     mov.l        (%a1)+,FACT1HI(%a6)
  9032.     mov.l        (%a1)+,FACT1LOW(%a6)
  9033.     mov.w        (%a1)+,FACT2(%a6)
  9034.  
  9035.     fsub.x        %fp1,%fp0        # X - (1/64)*INT(64 X)
  9036.  
  9037.     mov.w        (%a1)+,FACT2HI(%a6)
  9038.     clr.w        FACT2HI+2(%a6)
  9039.     clr.l        FACT2LOW(%a6)
  9040.     add.w        %d1,FACT1(%a6)
  9041.     fmul.x        LOG2(%pc),%fp0        # FP0 IS R
  9042.     add.w        %d1,FACT2(%a6)
  9043.  
  9044.     bra.w        expr
  9045.  
  9046. EXPBORS:
  9047. #--FPCR, D0 SAVED
  9048.     cmp.l        %d1,&0x3FFF8000
  9049.     bgt.b        TEXPBIG
  9050.  
  9051. #--|X| IS SMALL, RETURN 1 + X
  9052.  
  9053.     fmov.l        %d0,%fpcr        # restore users round prec,mode
  9054.     fadd.s        &0x3F800000,%fp0    # RETURN 1 + X
  9055.     bra        t_pinx2
  9056.  
  9057. TEXPBIG:
  9058. #--|X| IS LARGE, GENERATE OVERFLOW IF X > 0; ELSE GENERATE UNDERFLOW
  9059. #--REGISTERS SAVE SO FAR ARE FPCR AND  D0
  9060.     mov.l        X(%a6),%d1
  9061.     cmp.l        %d1,&0
  9062.     blt.b        EXPNEG
  9063.  
  9064.     bra        t_ovfl2            # t_ovfl expects positive value
  9065.  
  9066. EXPNEG:
  9067.     bra        t_unfl2            # t_unfl expects positive value
  9068.  
  9069.     global        stwotoxd
  9070. stwotoxd:
  9071. #--ENTRY POINT FOR 2**(X) FOR DENORMALIZED ARGUMENT
  9072.  
  9073.     fmov.l        %d0,%fpcr        # set user's rounding mode/precision
  9074.     fmov.s        &0x3F800000,%fp0    # RETURN 1 + X
  9075.     mov.l        (%a0),%d1
  9076.     or.l        &0x00800001,%d1
  9077.     fadd.s        %d1,%fp0
  9078.     bra        t_pinx2
  9079.  
  9080.     global        stentox
  9081. #--ENTRY POINT FOR 10**(X), HERE X IS FINITE, NON-ZERO, AND NOT NAN'S
  9082. stentox:
  9083.     fmovm.x        (%a0),&0x80        # LOAD INPUT
  9084.  
  9085.     mov.l        (%a0),%d1
  9086.     mov.w        4(%a0),%d1
  9087.     fmov.x        %fp0,X(%a6)
  9088.     and.l        &0x7FFFFFFF,%d1
  9089.  
  9090.     cmp.l        %d1,&0x3FB98000        # |X| >= 2**(-70)?
  9091.     bge.b        TENOK1
  9092.     bra.w        EXPBORS
  9093.  
  9094. TENOK1:
  9095.     cmp.l        %d1,&0x400B9B07        # |X| <= 16480*log2/log10 ?
  9096.     ble.b        TENMAIN
  9097.     bra.w        EXPBORS
  9098.  
  9099. TENMAIN:
  9100. #--USUAL CASE, 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10
  9101.  
  9102.     fmov.x        %fp0,%fp1
  9103.     fmul.d        L2TEN64(%pc),%fp1    # X*64*LOG10/LOG2
  9104.     fmov.l        %fp1,INT(%a6)        # N=INT(X*64*LOG10/LOG2)
  9105.     mov.l        %d2,-(%sp)
  9106.     lea        TEXPTBL(%pc),%a1    # LOAD ADDRESS OF TABLE OF 2^(J/64)
  9107.     fmov.l        INT(%a6),%fp1        # N --> FLOATING FMT
  9108.     mov.l        INT(%a6),%d1
  9109.     mov.l        %d1,%d2
  9110.     and.l        &0x3F,%d1        # D0 IS J
  9111.     asl.l        &4,%d1            # DISPLACEMENT FOR 2^(J/64)
  9112.     add.l        %d1,%a1            # ADDRESS FOR 2^(J/64)
  9113.     asr.l        &6,%d2            # d2 IS L, N = 64L + J
  9114.     mov.l        %d2,%d1
  9115.     asr.l        &1,%d1            # D0 IS M
  9116.     sub.l        %d1,%d2            # d2 IS M', N = 64(M+M') + J
  9117.     add.l        &0x3FFF,%d2
  9118.  
  9119. #--SUMMARY: a1 IS ADDRESS FOR THE LEADING PORTION OF 2^(J/64),
  9120. #--D0 IS M WHERE N = 64(M+M') + J. NOTE THAT |M| <= 16140 BY DESIGN.
  9121. #--ADJFACT = 2^(M').
  9122. #--REGISTERS SAVED SO FAR ARE (IN ORDER) FPCR, D0, FP1, a1, AND FP2.
  9123.     fmovm.x        &0x0c,-(%sp)        # save fp2/fp3
  9124.  
  9125.     fmov.x        %fp1,%fp2
  9126.  
  9127.     fmul.d        L10TWO1(%pc),%fp1    # N*(LOG2/64LOG10)_LEAD
  9128.     mov.l        (%a1)+,FACT1(%a6)
  9129.  
  9130.     fmul.x        L10TWO2(%pc),%fp2    # N*(LOG2/64LOG10)_TRAIL
  9131.  
  9132.     mov.l        (%a1)+,FACT1HI(%a6)
  9133.     mov.l        (%a1)+,FACT1LOW(%a6)
  9134.     fsub.x        %fp1,%fp0        # X - N L_LEAD
  9135.     mov.w        (%a1)+,FACT2(%a6)
  9136.  
  9137.     fsub.x        %fp2,%fp0        # X - N L_TRAIL
  9138.  
  9139.     mov.w        (%a1)+,FACT2HI(%a6)
  9140.     clr.w        FACT2HI+2(%a6)
  9141.     clr.l        FACT2LOW(%a6)
  9142.  
  9143.     fmul.x        LOG10(%pc),%fp0        # FP0 IS R
  9144.     add.w        %d1,FACT1(%a6)
  9145.     add.w        %d1,FACT2(%a6)
  9146.  
  9147. expr:
  9148. #--FPCR, FP2, FP3 ARE SAVED IN ORDER AS SHOWN.
  9149. #--ADJFACT CONTAINS 2**(M'), FACT1 + FACT2 = 2**(M) * 2**(J/64).
  9150. #--FP0 IS R. THE FOLLOWING CODE COMPUTES
  9151. #--    2**(M'+M) * 2**(J/64) * EXP(R)
  9152.  
  9153.     fmov.x        %fp0,%fp1
  9154.     fmul.x        %fp1,%fp1        # FP1 IS S = R*R
  9155.  
  9156.     fmov.d        EXPA5(%pc),%fp2        # FP2 IS A5
  9157.     fmov.d        EXPA4(%pc),%fp3        # FP3 IS A4
  9158.  
  9159.     fmul.x        %fp1,%fp2        # FP2 IS S*A5
  9160.     fmul.x        %fp1,%fp3        # FP3 IS S*A4
  9161.  
  9162.     fadd.d        EXPA3(%pc),%fp2        # FP2 IS A3+S*A5
  9163.     fadd.d        EXPA2(%pc),%fp3        # FP3 IS A2+S*A4
  9164.  
  9165.     fmul.x        %fp1,%fp2        # FP2 IS S*(A3+S*A5)
  9166.     fmul.x        %fp1,%fp3        # FP3 IS S*(A2+S*A4)
  9167.  
  9168.     fadd.d        EXPA1(%pc),%fp2        # FP2 IS A1+S*(A3+S*A5)
  9169.     fmul.x        %fp0,%fp3        # FP3 IS R*S*(A2+S*A4)
  9170.  
  9171.     fmul.x        %fp1,%fp2        # FP2 IS S*(A1+S*(A3+S*A5))
  9172.     fadd.x        %fp3,%fp0        # FP0 IS R+R*S*(A2+S*A4)
  9173.     fadd.x        %fp2,%fp0        # FP0 IS EXP(R) - 1
  9174.  
  9175.     fmovm.x        (%sp)+,&0x30        # restore fp2/fp3
  9176.  
  9177. #--FINAL RECONSTRUCTION PROCESS
  9178. #--EXP(X) = 2^M*2^(J/64) + 2^M*2^(J/64)*(EXP(R)-1)  -  (1 OR 0)
  9179.  
  9180.     fmul.x        FACT1(%a6),%fp0
  9181.     fadd.x        FACT2(%a6),%fp0
  9182.     fadd.x        FACT1(%a6),%fp0
  9183.  
  9184.     fmov.l        %d0,%fpcr        # restore users round prec,mode
  9185.     mov.w        %d2,ADJFACT(%a6)    # INSERT EXPONENT
  9186.     mov.l        (%sp)+,%d2
  9187.     mov.l        &0x80000000,ADJFACT+4(%a6)
  9188.     clr.l        ADJFACT+8(%a6)
  9189.     mov.b        &FMUL_OP,%d1        # last inst is MUL
  9190.     fmul.x        ADJFACT(%a6),%fp0    # FINAL ADJUSTMENT
  9191.     bra        t_catch
  9192.  
  9193.     global        stentoxd
  9194. stentoxd:
  9195. #--ENTRY POINT FOR 10**(X) FOR DENORMALIZED ARGUMENT
  9196.  
  9197.     fmov.l        %d0,%fpcr        # set user's rounding mode/precision
  9198.     fmov.s        &0x3F800000,%fp0    # RETURN 1 + X
  9199.     mov.l        (%a0),%d1
  9200.     or.l        &0x00800001,%d1
  9201.     fadd.s        %d1,%fp0
  9202.     bra        t_pinx2
  9203.  
  9204. #########################################################################
  9205. # sscale(): computes the destination operand scaled by the source    #
  9206. #        operand. If the absoulute value of the source operand is     #
  9207. #        >= 2^14, an overflow or underflow is returned.        #
  9208. #                                    #
  9209. # INPUT *************************************************************** #
  9210. #    a0  = pointer to double-extended source operand X        #
  9211. #    a1  = pointer to double-extended destination operand Y        #
  9212. #                                    #
  9213. # OUTPUT ************************************************************** #
  9214. #    fp0 =  scale(X,Y)                        #
  9215. #                                    #
  9216. #########################################################################
  9217.  
  9218. set    SIGN,        L_SCR1
  9219.  
  9220.     global        sscale
  9221. sscale:
  9222.     mov.l        %d0,-(%sp)        # store off ctrl bits for now
  9223.  
  9224.     mov.w        DST_EX(%a1),%d1        # get dst exponent
  9225.     smi.b        SIGN(%a6)        # use SIGN to hold dst sign
  9226.     andi.l        &0x00007fff,%d1        # strip sign from dst exp
  9227.  
  9228.     mov.w        SRC_EX(%a0),%d0        # check src bounds
  9229.     andi.w        &0x7fff,%d0        # clr src sign bit
  9230.     cmpi.w        %d0,&0x3fff        # is src ~ ZERO?
  9231.     blt.w        src_small        # yes
  9232.     cmpi.w        %d0,&0x400c        # no; is src too big?
  9233.     bgt.w        src_out            # yes
  9234.  
  9235. #
  9236. # Source is within 2^14 range.
  9237. #
  9238. src_ok:
  9239.     fintrz.x    SRC(%a0),%fp0        # calc int of src
  9240.     fmov.l        %fp0,%d0        # int src to d0
  9241. # don't want any accrued bits from the fintrz showing up later since
  9242. # we may need to read the fpsr for the last fp op in t_catch2().
  9243.     fmov.l        &0x0,%fpsr
  9244.  
  9245.     tst.b        DST_HI(%a1)        # is dst denormalized?
  9246.     bmi.b        sok_norm
  9247.  
  9248. # the dst is a DENORM. normalize the DENORM and add the adjustment to
  9249. # the src value. then, jump to the norm part of the routine.
  9250. sok_dnrm:
  9251.     mov.l        %d0,-(%sp)        # save src for now
  9252.  
  9253.     mov.w        DST_EX(%a1),FP_SCR0_EX(%a6) # make a copy
  9254.     mov.l        DST_HI(%a1),FP_SCR0_HI(%a6)
  9255.     mov.l        DST_LO(%a1),FP_SCR0_LO(%a6)
  9256.  
  9257.     lea        FP_SCR0(%a6),%a0    # pass ptr to DENORM
  9258.     bsr.l        norm            # normalize the DENORM
  9259.     neg.l        %d0
  9260.     add.l        (%sp)+,%d0        # add adjustment to src
  9261.  
  9262.     fmovm.x        FP_SCR0(%a6),&0x80    # load normalized DENORM
  9263.  
  9264.     cmpi.w        %d0,&-0x3fff        # is the shft amt really low?
  9265.     bge.b        sok_norm2        # thank goodness no
  9266.  
  9267. # the multiply factor that we're trying to create should be a denorm
  9268. # for the multiply to work. therefore, we're going to actually do a 
  9269. # multiply with a denorm which will cause an unimplemented data type
  9270. # exception to be put into the machine which will be caught and corrected
  9271. # later. we don't do this with the DENORMs above because this method
  9272. # is slower. but, don't fret, I don't see it being used much either.
  9273.     fmov.l        (%sp)+,%fpcr        # restore user fpcr
  9274.     mov.l        &0x80000000,%d1        # load normalized mantissa
  9275.     subi.l        &-0x3fff,%d0        # how many should we shift?
  9276.     neg.l        %d0            # make it positive
  9277.     cmpi.b        %d0,&0x20        # is it > 32?
  9278.     bge.b        sok_dnrm_32        # yes
  9279.     lsr.l        %d0,%d1            # no; bit stays in upper lw
  9280.     clr.l        -(%sp)            # insert zero low mantissa
  9281.     mov.l        %d1,-(%sp)        # insert new high mantissa
  9282.     clr.l        -(%sp)            # make zero exponent
  9283.     bra.b        sok_norm_cont    
  9284. sok_dnrm_32:
  9285.     subi.b        &0x20,%d0        # get shift count
  9286.     lsr.l        %d0,%d1            # make low mantissa longword
  9287.     mov.l        %d1,-(%sp)        # insert new low mantissa
  9288.     clr.l        -(%sp)            # insert zero high mantissa
  9289.     clr.l        -(%sp)            # make zero exponent
  9290.     bra.b        sok_norm_cont
  9291.     
  9292. # the src will force the dst to a DENORM value or worse. so, let's
  9293. # create an fp multiply that will create the result.
  9294. sok_norm:
  9295.     fmovm.x        DST(%a1),&0x80        # load fp0 with normalized src
  9296. sok_norm2:
  9297.     fmov.l        (%sp)+,%fpcr        # restore user fpcr
  9298.  
  9299.     addi.w        &0x3fff,%d0        # turn src amt into exp value
  9300.     swap        %d0            # put exponent in high word
  9301.     clr.l        -(%sp)            # insert new exponent
  9302.     mov.l        &0x80000000,-(%sp)    # insert new high mantissa
  9303.     mov.l        %d0,-(%sp)        # insert new lo mantissa
  9304.  
  9305. sok_norm_cont:
  9306.     fmov.l        %fpcr,%d0        # d0 needs fpcr for t_catch2
  9307.     mov.b        &FMUL_OP,%d1        # last inst is MUL
  9308.     fmul.x        (%sp)+,%fp0        # do the multiply
  9309.     bra        t_catch2        # catch any exceptions
  9310.  
  9311. #
  9312. # Source is outside of 2^14 range.  Test the sign and branch
  9313. # to the appropriate exception handler.
  9314. #
  9315. src_out:
  9316.     mov.l        (%sp)+,%d0        # restore ctrl bits
  9317.     exg        %a0,%a1            # swap src,dst ptrs
  9318.     tst.b        SRC_EX(%a1)        # is src negative?
  9319.     bmi        t_unfl            # yes; underflow
  9320.     bra        t_ovfl_sc        # no; overflow
  9321.  
  9322. #
  9323. # The source input is below 1, so we check for denormalized numbers
  9324. # and set unfl.
  9325. #
  9326. src_small:
  9327.     tst.b        DST_HI(%a1)        # is dst denormalized?
  9328.     bpl.b        ssmall_done        # yes
  9329.  
  9330.     mov.l        (%sp)+,%d0
  9331.     fmov.l        %d0,%fpcr        # no; load control bits
  9332.     mov.b        &FMOV_OP,%d1        # last inst is MOVE
  9333.     fmov.x        DST(%a1),%fp0        # simply return dest
  9334.     bra        t_catch2
  9335. ssmall_done:
  9336.     mov.l        (%sp)+,%d0        # load control bits into d1
  9337.     mov.l        %a1,%a0            # pass ptr to dst
  9338.     bra        t_resdnrm
  9339.  
  9340. #########################################################################
  9341. # smod(): computes the fp MOD of the input values X,Y.            #
  9342. # srem(): computes the fp (IEEE) REM of the input values X,Y.        #
  9343. #                                    #
  9344. # INPUT *************************************************************** #
  9345. #    a0 = pointer to extended precision input X            #
  9346. #    a1 = pointer to extended precision input Y            #
  9347. #    d0 = round precision,mode                    #
  9348. #                                    #
  9349. #     The input operands X and Y can be either normalized or         #
  9350. #    denormalized.                            #
  9351. #                                    #
  9352. # OUTPUT ************************************************************** #
  9353. #      fp0 = FREM(X,Y) or FMOD(X,Y)                    #
  9354. #                                    #
  9355. # ALGORITHM *********************************************************** #
  9356. #                                    #
  9357. #       Step 1.  Save and strip signs of X and Y: signX := sign(X),    #
  9358. #                signY := sign(Y), X := |X|, Y := |Y|,             #
  9359. #                signQ := signX EOR signY. Record whether MOD or REM    #
  9360. #                is requested.                        #
  9361. #                                    #
  9362. #       Step 2.  Set L := expo(X)-expo(Y), k := 0, Q := 0.        #
  9363. #                If (L < 0) then                    #
  9364. #                   R := X, go to Step 4.                #
  9365. #                else                            #
  9366. #                   R := 2^(-L)X, j := L.                #
  9367. #                endif                            #
  9368. #                                    #
  9369. #       Step 3.  Perform MOD(X,Y)                    #
  9370. #            3.1 If R = Y, go to Step 9.                #
  9371. #            3.2 If R > Y, then { R := R - Y, Q := Q + 1}        #
  9372. #            3.3 If j = 0, go to Step 4.                #
  9373. #            3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to    #
  9374. #                Step 3.1.                        #
  9375. #                                    #
  9376. #       Step 4.  At this point, R = X - QY = MOD(X,Y). Set        #
  9377. #                Last_Subtract := false (used in Step 7 below). If    #
  9378. #                MOD is requested, go to Step 6.             #
  9379. #                                    #
  9380. #       Step 5.  R = MOD(X,Y), but REM(X,Y) is requested.        #
  9381. #            5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to    #
  9382. #                Step 6.                        #
  9383. #            5.2 If R > Y/2, then { set Last_Subtract := true,        #
  9384. #                Q := Q + 1, Y := signY*Y }. Go to Step 6.        #
  9385. #            5.3 This is the tricky case of R = Y/2. If Q is odd,    #
  9386. #                then { Q := Q + 1, signX := -signX }.            #
  9387. #                                    #
  9388. #       Step 6.  R := signX*R.                        #
  9389. #                                    #
  9390. #       Step 7.  If Last_Subtract = true, R := R - Y.            #
  9391. #                                    #
  9392. #       Step 8.  Return signQ, last 7 bits of Q, and R as required.    #
  9393. #                                    #
  9394. #       Step 9.  At this point, R = 2^(-j)*X - Q Y = Y. Thus,        #
  9395. #                X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1),        #
  9396. #                R := 0. Return signQ, last 7 bits of Q, and R.        #
  9397. #                                    #
  9398. #########################################################################
  9399.  
  9400.     set        Mod_Flag,L_SCR3
  9401.     set        Sc_Flag,L_SCR3+1
  9402.  
  9403.     set        SignY,L_SCR2
  9404.     set        SignX,L_SCR2+2
  9405.     set        SignQ,L_SCR3+2
  9406.  
  9407.     set        Y,FP_SCR0
  9408.     set        Y_Hi,Y+4
  9409.     set        Y_Lo,Y+8
  9410.  
  9411.     set        R,FP_SCR1
  9412.     set        R_Hi,R+4
  9413.     set        R_Lo,R+8
  9414.  
  9415. Scale:
  9416.     long        0x00010000,0x80000000,0x00000000,0x00000000
  9417.  
  9418.     global        smod
  9419. smod:
  9420.     clr.b        FPSR_QBYTE(%a6)
  9421.     mov.l        %d0,-(%sp)        # save ctrl bits
  9422.     clr.b        Mod_Flag(%a6)
  9423.     bra.b        Mod_Rem
  9424.  
  9425.     global        srem
  9426. srem:
  9427.     clr.b        FPSR_QBYTE(%a6)
  9428.     mov.l        %d0,-(%sp)        # save ctrl bits
  9429.     mov.b        &0x1,Mod_Flag(%a6)
  9430.  
  9431. Mod_Rem:
  9432. #..Save sign of X and Y
  9433.     movm.l        &0x3f00,-(%sp)        # save data registers
  9434.     mov.w        SRC_EX(%a0),%d3
  9435.     mov.w        %d3,SignY(%a6)
  9436.     and.l        &0x00007FFF,%d3        # Y := |Y|
  9437.  
  9438. #
  9439.     mov.l        SRC_HI(%a0),%d4
  9440.     mov.l        SRC_LO(%a0),%d5        # (D3,D4,D5) is |Y|
  9441.  
  9442.     tst.l        %d3
  9443.     bne.b        Y_Normal
  9444.  
  9445.     mov.l        &0x00003FFE,%d3        # $3FFD + 1
  9446.     tst.l        %d4
  9447.     bne.b        HiY_not0
  9448.  
  9449. HiY_0:
  9450.     mov.l        %d5,%d4
  9451.     clr.l        %d5
  9452.     sub.l        &32,%d3
  9453.     clr.l        %d6
  9454.     bfffo        %d4{&0:&32},%d6
  9455.     lsl.l        %d6,%d4
  9456.     sub.l        %d6,%d3            # (D3,D4,D5) is normalized
  9457. #                                            ...with bias $7FFD
  9458.     bra.b        Chk_X
  9459.  
  9460. HiY_not0:
  9461.     clr.l        %d6
  9462.     bfffo        %d4{&0:&32},%d6
  9463.     sub.l        %d6,%d3
  9464.     lsl.l        %d6,%d4
  9465.     mov.l        %d5,%d7            # a copy of D5
  9466.     lsl.l        %d6,%d5
  9467.     neg.l        %d6
  9468.     add.l        &32,%d6
  9469.     lsr.l        %d6,%d7
  9470.     or.l        %d7,%d4            # (D3,D4,D5) normalized
  9471. #                                       ...with bias $7FFD
  9472.     bra.b        Chk_X
  9473.  
  9474. Y_Normal:
  9475.     add.l        &0x00003FFE,%d3        # (D3,D4,D5) normalized
  9476. #                                       ...with bias $7FFD
  9477.  
  9478. Chk_X:
  9479.     mov.w        DST_EX(%a1),%d0
  9480.     mov.w        %d0,SignX(%a6)
  9481.     mov.w        SignY(%a6),%d1
  9482.     eor.l        %d0,%d1
  9483.     and.l        &0x00008000,%d1
  9484.     mov.w        %d1,SignQ(%a6)        # sign(Q) obtained
  9485.     and.l        &0x00007FFF,%d0
  9486.     mov.l        DST_HI(%a1),%d1
  9487.     mov.l        DST_LO(%a1),%d2        # (D0,D1,D2) is |X|
  9488.     tst.l        %d0
  9489.     bne.b        X_Normal
  9490.     mov.l        &0x00003FFE,%d0
  9491.     tst.l        %d1
  9492.     bne.b        HiX_not0
  9493.  
  9494. HiX_0:
  9495.     mov.l        %d2,%d1
  9496.     clr.l        %d2
  9497.     sub.l        &32,%d0
  9498.     clr.l        %d6
  9499.     bfffo        %d1{&0:&32},%d6
  9500.     lsl.l        %d6,%d1
  9501.     sub.l        %d6,%d0            # (D0,D1,D2) is normalized
  9502. #                                       ...with bias $7FFD
  9503.     bra.b        Init
  9504.  
  9505. HiX_not0:
  9506.     clr.l        %d6
  9507.     bfffo        %d1{&0:&32},%d6
  9508.     sub.l        %d6,%d0
  9509.     lsl.l        %d6,%d1
  9510.     mov.l        %d2,%d7            # a copy of D2
  9511.     lsl.l        %d6,%d2
  9512.     neg.l        %d6
  9513.     add.l        &32,%d6
  9514.     lsr.l        %d6,%d7
  9515.     or.l        %d7,%d1            # (D0,D1,D2) normalized
  9516. #                                       ...with bias $7FFD
  9517.     bra.b        Init
  9518.  
  9519. X_Normal:
  9520.     add.l        &0x00003FFE,%d0        # (D0,D1,D2) normalized
  9521. #                                       ...with bias $7FFD
  9522.  
  9523. Init:
  9524. #
  9525.     mov.l        %d3,L_SCR1(%a6)        # save biased exp(Y)
  9526.     mov.l        %d0,-(%sp)        # save biased exp(X)
  9527.     sub.l        %d3,%d0            # L := expo(X)-expo(Y)
  9528.  
  9529.     clr.l        %d6            # D6 := carry <- 0
  9530.     clr.l        %d3            # D3 is Q
  9531.     mov.l        &0,%a1            # A1 is k; j+k=L, Q=0
  9532.  
  9533. #..(Carry,D1,D2) is R
  9534.     tst.l        %d0
  9535.     bge.b        Mod_Loop_pre
  9536.  
  9537. #..expo(X) < expo(Y). Thus X = mod(X,Y)
  9538. #
  9539.     mov.l        (%sp)+,%d0        # restore d0
  9540.     bra.w        Get_Mod
  9541.  
  9542. Mod_Loop_pre:
  9543.     addq.l        &0x4,%sp        # erase exp(X)
  9544. #..At this point  R = 2^(-L)X; Q = 0; k = 0; and  k+j = L
  9545. Mod_Loop:
  9546.     tst.l        %d6            # test carry bit
  9547.     bgt.b        R_GT_Y
  9548.  
  9549. #..At this point carry = 0, R = (D1,D2), Y = (D4,D5)
  9550.     cmp.l        %d1,%d4            # compare hi(R) and hi(Y)
  9551.     bne.b        R_NE_Y
  9552.     cmp.l        %d2,%d5            # compare lo(R) and lo(Y)
  9553.     bne.b        R_NE_Y
  9554.  
  9555. #..At this point, R = Y
  9556.     bra.w        Rem_is_0
  9557.  
  9558. R_NE_Y:
  9559. #..use the borrow of the previous compare
  9560.     bcs.b        R_LT_Y            # borrow is set iff R < Y
  9561.  
  9562. R_GT_Y:
  9563. #..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0
  9564. #..and Y < (D1,D2) < 2Y. Either way, perform R - Y
  9565.     sub.l        %d5,%d2            # lo(R) - lo(Y)
  9566.     subx.l        %d4,%d1            # hi(R) - hi(Y)
  9567.     clr.l        %d6            # clear carry
  9568.     addq.l        &1,%d3            # Q := Q + 1
  9569.  
  9570. R_LT_Y:
  9571. #..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.
  9572.     tst.l        %d0            # see if j = 0.
  9573.     beq.b        PostLoop
  9574.  
  9575.     add.l        %d3,%d3            # Q := 2Q
  9576.     add.l        %d2,%d2            # lo(R) = 2lo(R)
  9577.     roxl.l        &1,%d1            # hi(R) = 2hi(R) + carry
  9578.     scs        %d6            # set Carry if 2(R) overflows
  9579.     addq.l        &1,%a1            # k := k+1
  9580.     subq.l        &1,%d0            # j := j - 1
  9581. #..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.
  9582.  
  9583.     bra.b        Mod_Loop
  9584.  
  9585. PostLoop:
  9586. #..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.
  9587.  
  9588. #..normalize R.
  9589.     mov.l        L_SCR1(%a6),%d0        # new biased expo of R
  9590.     tst.l        %d1
  9591.     bne.b        HiR_not0
  9592.  
  9593. HiR_0:
  9594.     mov.l        %d2,%d1
  9595.     clr.l        %d2
  9596.     sub.l        &32,%d0
  9597.     clr.l        %d6
  9598.     bfffo        %d1{&0:&32},%d6
  9599.     lsl.l        %d6,%d1
  9600.     sub.l        %d6,%d0            # (D0,D1,D2) is normalized
  9601. #                                       ...with bias $7FFD
  9602.     bra.b        Get_Mod
  9603.  
  9604. HiR_not0:
  9605.     clr.l        %d6
  9606.     bfffo        %d1{&0:&32},%d6
  9607.     bmi.b        Get_Mod            # already normalized
  9608.     sub.l        %d6,%d0
  9609.     lsl.l        %d6,%d1
  9610.     mov.l        %d2,%d7            # a copy of D2
  9611.     lsl.l        %d6,%d2
  9612.     neg.l        %d6
  9613.     add.l        &32,%d6
  9614.     lsr.l        %d6,%d7
  9615.     or.l        %d7,%d1            # (D0,D1,D2) normalized
  9616.  
  9617. #
  9618. Get_Mod:
  9619.     cmp.l        %d0,&0x000041FE
  9620.     bge.b        No_Scale
  9621. Do_Scale:
  9622.     mov.w        %d0,R(%a6)
  9623.     mov.l        %d1,R_Hi(%a6)
  9624.     mov.l        %d2,R_Lo(%a6)
  9625.     mov.l        L_SCR1(%a6),%d6
  9626.     mov.w        %d6,Y(%a6)
  9627.     mov.l        %d4,Y_Hi(%a6)
  9628.     mov.l        %d5,Y_Lo(%a6)
  9629.     fmov.x        R(%a6),%fp0        # no exception
  9630.     mov.b        &1,Sc_Flag(%a6)
  9631.     bra.b        ModOrRem
  9632. No_Scale:
  9633.     mov.l        %d1,R_Hi(%a6)
  9634.     mov.l        %d2,R_Lo(%a6)
  9635.     sub.l        &0x3FFE,%d0
  9636.     mov.w        %d0,R(%a6)
  9637.     mov.l        L_SCR1(%a6),%d6
  9638.     sub.l        &0x3FFE,%d6
  9639.     mov.l        %d6,L_SCR1(%a6)
  9640.     fmov.x        R(%a6),%fp0
  9641.     mov.w        %d6,Y(%a6)
  9642.     mov.l        %d4,Y_Hi(%a6)
  9643.     mov.l        %d5,Y_Lo(%a6)
  9644.     clr.b        Sc_Flag(%a6)
  9645.  
  9646. #
  9647. ModOrRem:
  9648.     tst.b        Mod_Flag(%a6)
  9649.     beq.b        Fix_Sign
  9650.  
  9651.     mov.l        L_SCR1(%a6),%d6        # new biased expo(Y)
  9652.     subq.l        &1,%d6            # biased expo(Y/2)
  9653.     cmp.l        %d0,%d6
  9654.     blt.b        Fix_Sign
  9655.     bgt.b        Last_Sub
  9656.  
  9657.     cmp.l        %d1,%d4
  9658.     bne.b        Not_EQ
  9659.     cmp.l        %d2,%d5
  9660.     bne.b        Not_EQ
  9661.     bra.w        Tie_Case
  9662.  
  9663. Not_EQ:
  9664.     bcs.b        Fix_Sign
  9665.  
  9666. Last_Sub:
  9667. #
  9668.     fsub.x        Y(%a6),%fp0        # no exceptions
  9669.     addq.l        &1,%d3            # Q := Q + 1
  9670.  
  9671. #
  9672. Fix_Sign:
  9673. #..Get sign of X
  9674.     mov.w        SignX(%a6),%d6
  9675.     bge.b        Get_Q
  9676.     fneg.x        %fp0
  9677.  
  9678. #..Get Q
  9679. #
  9680. Get_Q:
  9681.     clr.l        %d6
  9682.     mov.w        SignQ(%a6),%d6        # D6 is sign(Q)
  9683.     mov.l        &8,%d7
  9684.     lsr.l        %d7,%d6
  9685.     and.l        &0x0000007F,%d3        # 7 bits of Q
  9686.     or.l        %d6,%d3            # sign and bits of Q
  9687. #    swap        %d3
  9688. #    fmov.l        %fpsr,%d6
  9689. #    and.l        &0xFF00FFFF,%d6
  9690. #    or.l        %d3,%d6
  9691. #    fmov.l        %d6,%fpsr        # put Q in fpsr
  9692.     mov.b        %d3,FPSR_QBYTE(%a6)    # put Q in fpsr
  9693.  
  9694. #
  9695. Restore:
  9696.     movm.l        (%sp)+,&0xfc        #  {%d2-%d7}
  9697.     mov.l        (%sp)+,%d0
  9698.     fmov.l        %d0,%fpcr
  9699.     tst.b        Sc_Flag(%a6)
  9700.     beq.b        Finish
  9701.     mov.b        &FMUL_OP,%d1        # last inst is MUL
  9702.     fmul.x        Scale(%pc),%fp0        # may cause underflow
  9703.     bra        t_catch2
  9704. # the '040 package did this apparently to see if the dst operand for the 
  9705. # preceding fmul was a denorm. but, it better not have been since the 
  9706. # algorithm just got done playing with fp0 and expected no exceptions
  9707. # as a result. trust me...
  9708. #    bra        t_avoid_unsupp        # check for denorm as a
  9709. #                        ;result of the scaling
  9710.  
  9711. Finish:
  9712.     mov.b        &FMOV_OP,%d1        # last inst is MOVE
  9713.     fmov.x        %fp0,%fp0        # capture exceptions & round
  9714.     bra        t_catch2
  9715.  
  9716. Rem_is_0:
  9717. #..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)
  9718.     addq.l        &1,%d3
  9719.     cmp.l        %d0,&8            # D0 is j 
  9720.     bge.b        Q_Big
  9721.  
  9722.     lsl.l        %d0,%d3
  9723.     bra.b        Set_R_0
  9724.  
  9725. Q_Big:
  9726.     clr.l        %d3
  9727.  
  9728. Set_R_0:
  9729.     fmov.s        &0x00000000,%fp0
  9730.     clr.b        Sc_Flag(%a6)
  9731.     bra.w        Fix_Sign
  9732.  
  9733. Tie_Case:
  9734. #..Check parity of Q
  9735.     mov.l        %d3,%d6
  9736.     and.l        &0x00000001,%d6
  9737.     tst.l        %d6
  9738.     beq.w        Fix_Sign        # Q is even
  9739.  
  9740. #..Q is odd, Q := Q + 1, signX := -signX
  9741.     addq.l        &1,%d3
  9742.     mov.w        SignX(%a6),%d6
  9743.     eor.l        &0x00008000,%d6
  9744.     mov.w        %d6,SignX(%a6)
  9745.     bra.w        Fix_Sign
  9746.  
  9747. #########################################################################
  9748. # XDEF ****************************************************************    #
  9749. #     tag(): return the optype of the input ext fp number        #
  9750. #                                    #
  9751. #    This routine is used by the 060FPLSP.                #
  9752. #                                    #
  9753. # XREF ****************************************************************    #
  9754. #    None                                #
  9755. #                                    #
  9756. # INPUT ***************************************************************    #
  9757. #    a0 = pointer to extended precision operand            #
  9758. #                                     #
  9759. # OUTPUT **************************************************************    #
  9760. #    d0 = value of type tag                        #
  9761. #         one of: NORM, INF, QNAN, SNAN, DENORM, ZERO        #
  9762. #                                    #
  9763. # ALGORITHM ***********************************************************    #
  9764. #    Simply test the exponent, j-bit, and mantissa values to     #
  9765. # determine the type of operand.                    #
  9766. #    If it's an unnormalized zero, alter the operand and force it    #
  9767. # to be a normal zero.                            #
  9768. #                                    #
  9769. #########################################################################
  9770.  
  9771.     global        tag
  9772. tag:
  9773.     mov.w        FTEMP_EX(%a0), %d0    # extract exponent
  9774.     andi.w        &0x7fff, %d0        # strip off sign
  9775.     cmpi.w        %d0, &0x7fff        # is (EXP == MAX)?
  9776.     beq.b        inf_or_nan_x
  9777. not_inf_or_nan_x:
  9778.     btst        &0x7,FTEMP_HI(%a0)
  9779.     beq.b        not_norm_x
  9780. is_norm_x:
  9781.     mov.b        &NORM, %d0
  9782.     rts
  9783. not_norm_x:
  9784.     tst.w        %d0            # is exponent = 0?
  9785.     bne.b        is_unnorm_x
  9786. not_unnorm_x:
  9787.     tst.l        FTEMP_HI(%a0)
  9788.     bne.b        is_denorm_x
  9789.     tst.l        FTEMP_LO(%a0)
  9790.     bne.b        is_denorm_x
  9791. is_zero_x:
  9792.     mov.b        &ZERO, %d0
  9793.     rts
  9794. is_denorm_x:
  9795.     mov.b        &DENORM, %d0
  9796.     rts
  9797. is_unnorm_x:
  9798.     bsr.l        unnorm_fix        # convert to norm,denorm,or zero
  9799.     rts
  9800. is_unnorm_reg_x:
  9801.     mov.b        &UNNORM, %d0
  9802.     rts
  9803. inf_or_nan_x:
  9804.     tst.l        FTEMP_LO(%a0)
  9805.     bne.b        is_nan_x
  9806.     mov.l        FTEMP_HI(%a0), %d0
  9807.     and.l        &0x7fffffff, %d0    # msb is a don't care!
  9808.     bne.b        is_nan_x
  9809. is_inf_x:
  9810.     mov.b        &INF, %d0
  9811.     rts
  9812. is_nan_x:
  9813.     mov.b        &QNAN, %d0
  9814.     rts
  9815.  
  9816. #############################################################
  9817.  
  9818. qnan:    long        0x7fff0000, 0xffffffff, 0xffffffff
  9819.  
  9820. #########################################################################
  9821. # XDEF ****************************************************************    #
  9822. #    t_dz(): Handle 060FPLSP dz exception for "flogn" emulation.    #
  9823. #    t_dz2(): Handle 060FPLSP dz exception for "fatanh" emulation.    #
  9824. #                                    #
  9825. #    These rouitnes are used by the 060FPLSP package.        #
  9826. #                                    #
  9827. # XREF ****************************************************************    #
  9828. #    None                                #
  9829. #                                    #
  9830. # INPUT ***************************************************************    #
  9831. #    a0 = pointer to extended precision source operand.        #
  9832. #                                     #
  9833. # OUTPUT **************************************************************    #
  9834. #    fp0 = default DZ result.                    #
  9835. #                                    #
  9836. # ALGORITHM ***********************************************************    #
  9837. #    Transcendental emulation for the 060FPLSP has detected that     #
  9838. # a DZ exception should occur for the instruction. If DZ is disabled,    #
  9839. # return the default result.                        #
  9840. #     If DZ is enabled, the dst operand should be returned unscathed    #
  9841. # in fp0 while fp1 is used to create a DZ exception so that the        #
  9842. # operating system can log that such an event occurred.            #
  9843. #                                    #
  9844. #########################################################################
  9845.  
  9846.     global        t_dz
  9847. t_dz:
  9848.     tst.b        SRC_EX(%a0)        # check sign for neg or pos
  9849.     bpl.b        dz_pinf            # branch if pos sign
  9850.  
  9851.     global        t_dz2
  9852. t_dz2:
  9853.     ori.l        &dzinf_mask+neg_mask,USER_FPSR(%a6) # set N/I/DZ/ADZ
  9854.  
  9855.     btst        &dz_bit,FPCR_ENABLE(%a6)
  9856.     bne.b        dz_minf_ena
  9857.  
  9858. # dz is disabled. return a -INF.
  9859.     fmov.s        &0xff800000,%fp0    # return -INF
  9860.     rts
  9861.  
  9862. # dz is enabled. create a dz exception so the user can record it
  9863. # but use fp1 instead. return the dst operand unscathed in fp0.
  9864. dz_minf_ena:
  9865.     fmovm.x        EXC_FP0(%a6),&0x80    # return fp0 unscathed
  9866.     fmov.l        USER_FPCR(%a6),%fpcr
  9867.     fmov.s        &0xbf800000,%fp1    # load -1
  9868.     fdiv.s        &0x00000000,%fp1    # -1 / 0
  9869.     rts
  9870.  
  9871. dz_pinf:
  9872.     ori.l        &dzinf_mask,USER_FPSR(%a6) # set I/DZ/ADZ
  9873.  
  9874.     btst        &dz_bit,FPCR_ENABLE(%a6)
  9875.     bne.b        dz_pinf_ena
  9876.  
  9877. # dz is disabled. return a +INF.
  9878.     fmov.s        &0x7f800000,%fp0    # return +INF
  9879.     rts
  9880.  
  9881. # dz is enabled. create a dz exception so the user can record it
  9882. # but use fp1 instead. return the dst operand unscathed in fp0.
  9883. dz_pinf_ena:
  9884.     fmovm.x        EXC_FP0(%a6),&0x80    # return fp0 unscathed
  9885.     fmov.l        USER_FPCR(%a6),%fpcr
  9886.     fmov.s        &0x3f800000,%fp1    # load +1
  9887.     fdiv.s        &0x00000000,%fp1    # +1 / 0
  9888.     rts
  9889.  
  9890. #########################################################################
  9891. # XDEF ****************************************************************    #
  9892. #    t_operr(): Handle 060FPLSP OPERR exception during emulation.    #
  9893. #                                    #
  9894. #    This routine is used by the 060FPLSP package.            #
  9895. #                                    #
  9896. # XREF ****************************************************************    #
  9897. #    None.                                #
  9898. #                                    #
  9899. # INPUT ***************************************************************    #
  9900. #    fp1 = source operand                        #
  9901. #                                     #
  9902. # OUTPUT **************************************************************    #
  9903. #    fp0 = default result                        #
  9904. #    fp1 = unchanged                            #
  9905. #                                    #
  9906. # ALGORITHM ***********************************************************    #
  9907. #    An operand error should occur as the result of transcendental    #
  9908. # emulation in the 060FPLSP. If OPERR is disabled, just return a NAN    #
  9909. # in fp0. If OPERR is enabled, return the dst operand unscathed in fp0    #
  9910. # and the source operand in fp1. Use fp2 to create an OPERR exception    #
  9911. # so that the operating system can log the event.            #
  9912. #                                    #
  9913. #########################################################################
  9914.  
  9915.     global        t_operr
  9916. t_operr:
  9917.     ori.l        &opnan_mask,USER_FPSR(%a6) # set NAN/OPERR/AIOP
  9918.  
  9919.     btst        &operr_bit,FPCR_ENABLE(%a6)
  9920.     bne.b        operr_ena
  9921.  
  9922. # operr is disabled. return a QNAN in fp0
  9923.     fmovm.x        qnan(%pc),&0x80        # return QNAN
  9924.     rts
  9925.  
  9926. # operr is enabled. create an operr exception so the user can record it
  9927. # but use fp2 instead. return the dst operand unscathed in fp0.
  9928. operr_ena:
  9929.     fmovm.x        EXC_FP0(%a6),&0x80    # return fp0 unscathed
  9930.     fmov.l        USER_FPCR(%a6),%fpcr    
  9931.     fmovm.x        &0x04,-(%sp)        # save fp2
  9932.     fmov.s        &0x7f800000,%fp2    # load +INF
  9933.     fmul.s        &0x00000000,%fp2    # +INF x 0
  9934.     fmovm.x        (%sp)+,&0x20        # restore fp2
  9935.     rts
  9936.  
  9937. pls_huge:
  9938.     long        0x7ffe0000,0xffffffff,0xffffffff
  9939. mns_huge:
  9940.     long        0xfffe0000,0xffffffff,0xffffffff
  9941. pls_tiny:
  9942.     long        0x00000000,0x80000000,0x00000000
  9943. mns_tiny:
  9944.     long        0x80000000,0x80000000,0x00000000
  9945.  
  9946. #########################################################################
  9947. # XDEF ****************************************************************    #
  9948. #    t_unfl(): Handle 060FPLSP underflow exception during emulation.    #
  9949. #    t_unfl2(): Handle 060FPLSP underflow exception during        #
  9950. #               emulation. result always positive.            #
  9951. #                                    #
  9952. #    This routine is used by the 060FPLSP package.            #
  9953. #                                    #
  9954. # XREF ****************************************************************    #
  9955. #    None.                                #
  9956. #                                    #
  9957. # INPUT ***************************************************************    #
  9958. #    a0 = pointer to extended precision source operand        #
  9959. #                                     #
  9960. # OUTPUT **************************************************************    #
  9961. #    fp0 = default underflow result                    #
  9962. #                                    #
  9963. # ALGORITHM ***********************************************************    #
  9964. #    An underflow should occur as the result of transcendental    #
  9965. # emulation in the 060FPLSP. Create an underflow by using "fmul"    #
  9966. # and two very small numbers of appropriate sign so the the operating    #
  9967. # system can log the event.                        #
  9968. #                                    #
  9969. #########################################################################
  9970.  
  9971.     global        t_unfl
  9972. t_unfl:
  9973.     tst.b        SRC_EX(%a0)
  9974.     bpl.b        unf_pos
  9975.  
  9976.     global        t_unfl2
  9977. t_unfl2:
  9978.     ori.l        &unfinx_mask+neg_mask,USER_FPSR(%a6) # set N/UNFL/INEX2/AUNFL/AINEX
  9979.  
  9980.     fmov.l        USER_FPCR(%a6),%fpcr
  9981.     fmovm.x        mns_tiny(%pc),&0x80
  9982.     fmul.x        pls_tiny(%pc),%fp0
  9983.  
  9984.     fmov.l        %fpsr,%d0
  9985.     rol.l        &0x8,%d0
  9986.     mov.b        %d0,FPSR_CC(%a6)
  9987.     rts
  9988. unf_pos:
  9989.     ori.w        &unfinx_mask,FPSR_EXCEPT(%a6) # set UNFL/INEX2/AUNFL/AINEX
  9990.  
  9991.     fmov.l        USER_FPCR(%a6),%fpcr
  9992.     fmovm.x        pls_tiny(%pc),&0x80
  9993.     fmul.x        %fp0,%fp0
  9994.  
  9995.     fmov.l        %fpsr,%d0
  9996.     rol.l        &0x8,%d0
  9997.     mov.b        %d0,FPSR_CC(%a6)
  9998.     rts
  9999.  
  10000. #########################################################################
  10001. # XDEF ****************************************************************    #
  10002. #    t_ovfl(): Handle 060FPLSP overflow exception during emulation.    #
  10003. #          (monadic)                        #
  10004. #    t_ovfl2(): Handle 060FPLSP overflow exception during        #
  10005. #               emulation. result always positive. (dyadic)        #
  10006. #    t_ovfl_sc(): Handle 060FPLSP overflow exception during         #
  10007. #                 emulation for "fscale".                 #
  10008. #                                    #
  10009. #    This routine is used by the 060FPLSP package.            #
  10010. #                                    #
  10011. # XREF ****************************************************************    #
  10012. #    None.                                #
  10013. #                                    #
  10014. # INPUT ***************************************************************    #
  10015. #    a0 = pointer to extended precision source operand        #
  10016. #                                     #
  10017. # OUTPUT **************************************************************    #
  10018. #    fp0 = default underflow result                    #
  10019. #                                    #
  10020. # ALGORITHM ***********************************************************    #
  10021. #    An overflow should occur as the result of transcendental    #
  10022. # emulation in the 060FPLSP. Create an overflow by using "fmul"        #
  10023. # and two very lareg numbers of appropriate sign so the the operating    #
  10024. # system can log the event.                        #
  10025. #    For t_ovfl_sc() we take special care not to lose the INEX2 bit.    #
  10026. #                                    #
  10027. #########################################################################
  10028.  
  10029.     global        t_ovfl_sc
  10030. t_ovfl_sc:
  10031.     ori.l        &ovfl_inx_mask,USER_FPSR(%a6) # set OVFL/AOVFL/AINEX
  10032.  
  10033.     mov.b        %d0,%d1            # fetch rnd prec,mode
  10034.     andi.b        &0xc0,%d1        # extract prec
  10035.     beq.w        ovfl_work
  10036.  
  10037. # dst op is a DENORM. we have to normalize the mantissa to see if the
  10038. # result would be inexact for the given precision. make a copy of the
  10039. # dst so we don't screw up the version passed to us.
  10040.     mov.w        LOCAL_EX(%a0),FP_SCR0_EX(%a6)
  10041.     mov.l        LOCAL_HI(%a0),FP_SCR0_HI(%a6)
  10042.     mov.l        LOCAL_LO(%a0),FP_SCR0_LO(%a6)
  10043.     lea        FP_SCR0(%a6),%a0    # pass ptr to FP_SCR0
  10044.     movm.l        &0xc080,-(%sp)        # save d0-d1/a0
  10045.     bsr.l        norm            # normalize mantissa
  10046.     movm.l        (%sp)+,&0x0103        # restore d0-d1/a0
  10047.  
  10048.     cmpi.b        %d1,&0x40        # is precision sgl?
  10049.     bne.b        ovfl_sc_dbl        # no; dbl
  10050. ovfl_sc_sgl:
  10051.     tst.l        LOCAL_LO(%a0)        # is lo lw of sgl set?
  10052.     bne.b        ovfl_sc_inx        # yes
  10053.     tst.b        3+LOCAL_HI(%a0)        # is lo byte of hi lw set?
  10054.     bne.b        ovfl_sc_inx        # yes
  10055.     bra.w        ovfl_work        # don't set INEX2
  10056. ovfl_sc_dbl:
  10057.     mov.l        LOCAL_LO(%a0),%d1    # are any of lo 11 bits of
  10058.     andi.l        &0x7ff,%d1        # dbl mantissa set?
  10059.     beq.w        ovfl_work        # no; don't set INEX2
  10060. ovfl_sc_inx:
  10061.     ori.l        &inex2_mask,USER_FPSR(%a6) # set INEX2
  10062.     bra.b        ovfl_work        # continue
  10063.  
  10064.     global        t_ovfl
  10065. t_ovfl:
  10066.     ori.w        &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
  10067. ovfl_work:
  10068.     tst.b        SRC_EX(%a0)
  10069.     bpl.b        ovfl_p
  10070. ovfl_m:
  10071.     fmov.l        USER_FPCR(%a6),%fpcr
  10072.     fmovm.x        mns_huge(%pc),&0x80
  10073.     fmul.x        pls_huge(%pc),%fp0
  10074.  
  10075.     fmov.l        %fpsr,%d0
  10076.     rol.l        &0x8,%d0
  10077.     ori.b        &neg_mask,%d0
  10078.     mov.b        %d0,FPSR_CC(%a6)
  10079.     rts
  10080. ovfl_p:
  10081.     fmov.l        USER_FPCR(%a6),%fpcr
  10082.     fmovm.x        pls_huge(%pc),&0x80
  10083.     fmul.x        pls_huge(%pc),%fp0
  10084.  
  10085.     fmov.l        %fpsr,%d0
  10086.     rol.l        &0x8,%d0
  10087.     mov.b        %d0,FPSR_CC(%a6)
  10088.     rts
  10089.  
  10090.     global        t_ovfl2
  10091. t_ovfl2:
  10092.     ori.w        &ovfinx_mask,FPSR_EXCEPT(%a6) # set OVFL/INEX2/AOVFL/AINEX
  10093.     fmov.l        USER_FPCR(%a6),%fpcr
  10094.     fmovm.x        pls_huge(%pc),&0x80
  10095.     fmul.x        pls_huge(%pc),%fp0
  10096.  
  10097.     fmov.l        %fpsr,%d0
  10098.     rol.l        &0x8,%d0
  10099.     mov.b        %d0,FPSR_CC(%a6)
  10100.     rts
  10101.  
  10102. #########################################################################
  10103. # XDEF ****************************************************************    #
  10104. #    t_catch(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during    #
  10105. #           emulation.                        #
  10106. #    t_catch2(): Handle 060FPLSP OVFL,UNFL,or INEX2 exception during    #
  10107. #            emulation.                        #
  10108. #                                    #
  10109. #    These routines are used by the 060FPLSP package.        #
  10110. #                                    #
  10111. # XREF ****************************************************************    #
  10112. #    None.                                #
  10113. #                                    #
  10114. # INPUT ***************************************************************    #
  10115. #    fp0 = default underflow or overflow result            #
  10116. #                                     #
  10117. # OUTPUT **************************************************************    #
  10118. #    fp0 = default result                        #
  10119. #                                    #
  10120. # ALGORITHM ***********************************************************    #
  10121. #     If an overflow or underflow occurred during the last         #
  10122. # instruction of transcendental 060FPLSP emulation, then it has already    #
  10123. # occurred and has been logged. Now we need to see if an inexact    #
  10124. # exception should occur.                        #
  10125. #                                    #
  10126. #########################################################################
  10127.  
  10128.     global        t_catch2
  10129. t_catch2:
  10130.     fmov.l        %fpsr,%d0
  10131.     or.l        %d0,USER_FPSR(%a6)
  10132.     bra.b        inx2_work
  10133.  
  10134.     global        t_catch
  10135. t_catch:
  10136.     fmov.l        %fpsr,%d0
  10137.     or.l        %d0,USER_FPSR(%a6)
  10138.  
  10139. #########################################################################
  10140. # XDEF ****************************************************************    #
  10141. #    t_inx2(): Handle inexact 060FPLSP exception during emulation.    #
  10142. #    t_pinx2(): Handle inexact 060FPLSP exception for "+" results.    #
  10143. #    t_minx2(): Handle inexact 060FPLSP exception for "-" results.    #
  10144. #                                    #
  10145. # XREF ****************************************************************    #
  10146. #    None.                                #
  10147. #                                    #
  10148. # INPUT ***************************************************************    #
  10149. #    fp0 = default result                        #
  10150. #                                     #
  10151. # OUTPUT **************************************************************    #
  10152. #    fp0 = default result                        #
  10153. #                                    #
  10154. # ALGORITHM ***********************************************************    #
  10155. #     The last instruction of transcendental emulation for the     #
  10156. # 060FPLSP should be inexact. So, if inexact is enabled, then we create    #
  10157. # the event here by adding a large and very small number together    #
  10158. # so that the operating system can log the event.            #
  10159. #     Must check, too, if the result was zero, in which case we just    #
  10160. # set the FPSR bits and return.                        #
  10161. #                                    #
  10162. #########################################################################
  10163.  
  10164.     global        t_inx2
  10165. t_inx2:
  10166.     fblt.w        t_minx2
  10167.     fbeq.w        inx2_zero
  10168.  
  10169.     global        t_pinx2
  10170. t_pinx2:
  10171.     ori.w        &inx2a_mask,FPSR_EXCEPT(%a6) # set INEX2/AINEX
  10172.     bra.b        inx2_work
  10173.  
  10174.     global        t_minx2
  10175. t_minx2:
  10176.     ori.l        &inx2a_mask+neg_mask,USER_FPSR(%a6)
  10177.  
  10178. inx2_work:
  10179.     btst        &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
  10180.     bne.b        inx2_work_ena        # yes
  10181.     rts    
  10182. inx2_work_ena:
  10183.     fmov.l        USER_FPCR(%a6),%fpcr    # insert user's exceptions
  10184.     fmov.s        &0x3f800000,%fp1    # load +1
  10185.     fadd.x        pls_tiny(%pc),%fp1    # cause exception
  10186.     rts
  10187.  
  10188. inx2_zero:
  10189.     mov.b        &z_bmask,FPSR_CC(%a6)
  10190.     ori.w        &inx2a_mask,2+USER_FPSR(%a6) # set INEX/AINEX
  10191.     rts
  10192.  
  10193. #########################################################################
  10194. # XDEF ****************************************************************    #
  10195. #    t_extdnrm(): Handle DENORM inputs in 060FPLSP.            #
  10196. #    t_resdnrm(): Handle DENORM inputs in 060FPLSP for "fscale".    #
  10197. #                                    #
  10198. #    This routine is used by the 060FPLSP package.            #
  10199. #                                    #
  10200. # XREF ****************************************************************    #
  10201. #    None.                                #
  10202. #                                    #
  10203. # INPUT ***************************************************************    #
  10204. #    a0 = pointer to extended precision input operand        #
  10205. #                                     #
  10206. # OUTPUT **************************************************************    #
  10207. #    fp0 = default result                        #
  10208. #                                    #
  10209. # ALGORITHM ***********************************************************    #
  10210. #    For all functions that have a denormalized input and that    #
  10211. # f(x)=x, this is the entry point.                    #
  10212. #    DENORM value is moved using "fmove" which triggers an exception    #
  10213. # if enabled so the operating system can log the event.            #
  10214. #                                    #
  10215. #########################################################################
  10216.  
  10217.     global        t_extdnrm
  10218. t_extdnrm:
  10219.     fmov.l        USER_FPCR(%a6),%fpcr
  10220.     fmov.x        SRC_EX(%a0),%fp0
  10221.     fmov.l        %fpsr,%d0
  10222.     ori.l        &unfinx_mask,%d0
  10223.     or.l        %d0,USER_FPSR(%a6)
  10224.     rts
  10225.  
  10226.     global        t_resdnrm
  10227. t_resdnrm:
  10228.     fmov.l        USER_FPCR(%a6),%fpcr
  10229.     fmov.x        SRC_EX(%a0),%fp0
  10230.     fmov.l        %fpsr,%d0
  10231.     or.l        %d0,USER_FPSR(%a6)
  10232.     rts
  10233.  
  10234. ##########################################
  10235.  
  10236. #
  10237. # sto_cos:
  10238. #     This is used by fsincos library emulation. The correct
  10239. # values are already in fp0 and fp1 so we do nothing here.
  10240. #
  10241.     global        sto_cos
  10242. sto_cos:
  10243.     rts
  10244.  
  10245. ##########################################
  10246.  
  10247. #
  10248. #    dst_qnan --- force result when destination is a NaN
  10249. #
  10250.     global        dst_qnan
  10251. dst_qnan:
  10252.     fmov.x        DST(%a1),%fp0
  10253.     tst.b        DST_EX(%a1)
  10254.     bmi.b        dst_qnan_m
  10255. dst_qnan_p:
  10256.     mov.b        &nan_bmask,FPSR_CC(%a6)
  10257.     rts
  10258. dst_qnan_m:
  10259.     mov.b        &nan_bmask+neg_bmask,FPSR_CC(%a6)
  10260.     rts
  10261.  
  10262. #
  10263. #    src_qnan --- force result when source is a NaN
  10264. #
  10265.     global        src_qnan
  10266. src_qnan:
  10267.     fmov.x        SRC(%a0),%fp0
  10268.     tst.b        SRC_EX(%a0)
  10269.     bmi.b        src_qnan_m
  10270. src_qnan_p:
  10271.     mov.b        &nan_bmask,FPSR_CC(%a6)
  10272.     rts
  10273. src_qnan_m:
  10274.     mov.b        &nan_bmask+neg_bmask,FPSR_CC(%a6)
  10275.     rts
  10276.  
  10277. ##########################################
  10278.  
  10279. #
  10280. #    Native instruction support
  10281. #
  10282. #    Some systems may need entry points even for 68060 native
  10283. #    instructions.  These routines are provided for
  10284. #    convenience.
  10285. #
  10286.     global        _fadds_
  10287. _fadds_:
  10288.     fmov.l        %fpcr,-(%sp)        # save fpcr
  10289.     fmov.l        &0x00000000,%fpcr    # clear fpcr for load
  10290.     fmov.s        0x8(%sp),%fp0        # load sgl dst
  10291.     fmov.l        (%sp)+,%fpcr        # restore fpcr
  10292.     fadd.s        0x8(%sp),%fp0        # fadd w/ sgl src
  10293.     rts
  10294.  
  10295.     global        _faddd_
  10296. _faddd_:
  10297.     fmov.l        %fpcr,-(%sp)        # save fpcr
  10298.     fmov.l        &0x00000000,%fpcr    # clear fpcr for load
  10299.     fmov.d        0x8(%sp),%fp0        # load dbl dst
  10300.     fmov.l        (%sp)+,%fpcr        # restore fpcr
  10301.     fadd.d        0xc(%sp),%fp0        # fadd w/ dbl src
  10302.     rts
  10303.  
  10304.     global        _faddx_
  10305. _faddx_:
  10306.     fmovm.x        0x4(%sp),&0x80        # load ext dst
  10307.     fadd.x        0x10(%sp),%fp0        # fadd w/ ext src
  10308.     rts
  10309.  
  10310.     global        _fsubs_
  10311. _fsubs_:
  10312.     fmov.l        %fpcr,-(%sp)        # save fpcr
  10313.     fmov.l        &0x00000000,%fpcr    # clear fpcr for load
  10314.     fmov.s        0x8(%sp),%fp0        # load sgl dst
  10315.     fmov.l        (%sp)+,%fpcr        # restore fpcr
  10316.     fsub.s        0x8(%sp),%fp0        # fsub w/ sgl src
  10317.     rts
  10318.  
  10319.     global        _fsubd_
  10320. _fsubd_:
  10321.     fmov.l        %fpcr,-(%sp)        # save fpcr
  10322.     fmov.l        &0x00000000,%fpcr    # clear fpcr for load
  10323.     fmov.d        0x8(%sp),%fp0        # load dbl dst
  10324.     fmov.l        (%sp)+,%fpcr        # restore fpcr
  10325.     fsub.d        0xc(%sp),%fp0        # fsub w/ dbl src
  10326.     rts
  10327.  
  10328.     global        _fsubx_
  10329. _fsubx_:
  10330.     fmovm.x        0x4(%sp),&0x80        # load ext dst
  10331.     fsub.x        0x10(%sp),%fp0        # fsub w/ ext src
  10332.     rts
  10333.  
  10334.     global        _fmuls_
  10335. _fmuls_:
  10336.     fmov.l        %fpcr,-(%sp)        # save fpcr
  10337.     fmov.l        &0x00000000,%fpcr    # clear fpcr for load
  10338.     fmov.s        0x8(%sp),%fp0        # load sgl dst
  10339.     fmov.l        (%sp)+,%fpcr        # restore fpcr
  10340.     fmul.s        0x8(%sp),%fp0        # fmul w/ sgl src
  10341.     rts
  10342.  
  10343.     global        _fmuld_
  10344. _fmuld_:
  10345.     fmov.l        %fpcr,-(%sp)        # save fpcr
  10346.     fmov.l        &0x00000000,%fpcr    # clear fpcr for load
  10347.     fmov.d        0x8(%sp),%fp0        # load dbl dst
  10348.     fmov.l        (%sp)+,%fpcr        # restore fpcr
  10349.     fmul.d        0xc(%sp),%fp0        # fmul w/ dbl src
  10350.     rts
  10351.  
  10352.     global        _fmulx_
  10353. _fmulx_:
  10354.     fmovm.x        0x4(%sp),&0x80        # load ext dst
  10355.     fmul.x        0x10(%sp),%fp0        # fmul w/ ext src
  10356.     rts
  10357.  
  10358.     global        _fdivs_
  10359. _fdivs_:
  10360.     fmov.l        %fpcr,-(%sp)        # save fpcr
  10361.     fmov.l        &0x00000000,%fpcr    # clear fpcr for load
  10362.     fmov.s        0x8(%sp),%fp0        # load sgl dst
  10363.     fmov.l        (%sp)+,%fpcr        # restore fpcr
  10364.     fdiv.s        0x8(%sp),%fp0        # fdiv w/ sgl src
  10365.     rts
  10366.  
  10367.     global        _fdivd_
  10368. _fdivd_:
  10369.     fmov.l        %fpcr,-(%sp)        # save fpcr
  10370.     fmov.l        &0x00000000,%fpcr    # clear fpcr for load
  10371.     fmov.d        0x8(%sp),%fp0        # load dbl dst
  10372.     fmov.l        (%sp)+,%fpcr        # restore fpcr
  10373.     fdiv.d        0xc(%sp),%fp0        # fdiv w/ dbl src
  10374.     rts
  10375.  
  10376.     global        _fdivx_
  10377. _fdivx_:
  10378.     fmovm.x        0x4(%sp),&0x80        # load ext dst
  10379.     fdiv.x        0x10(%sp),%fp0        # fdiv w/ ext src
  10380.     rts
  10381.  
  10382.     global        _fabss_
  10383. _fabss_:
  10384.     fabs.s        0x4(%sp),%fp0        # fabs w/ sgl src
  10385.     rts
  10386.  
  10387.     global        _fabsd_
  10388. _fabsd_:
  10389.     fabs.d        0x4(%sp),%fp0        # fabs w/ dbl src
  10390.     rts
  10391.  
  10392.     global        _fabsx_
  10393. _fabsx_:
  10394.     fabs.x        0x4(%sp),%fp0        # fabs w/ ext src
  10395.     rts
  10396.  
  10397.     global        _fnegs_
  10398. _fnegs_:
  10399.     fneg.s        0x4(%sp),%fp0        # fneg w/ sgl src
  10400.     rts
  10401.  
  10402.     global        _fnegd_
  10403. _fnegd_:
  10404.     fneg.d        0x4(%sp),%fp0        # fneg w/ dbl src
  10405.     rts
  10406.  
  10407.     global        _fnegx_
  10408. _fnegx_:
  10409.     fneg.x        0x4(%sp),%fp0        # fneg w/ ext src
  10410.     rts
  10411.  
  10412.     global        _fsqrts_
  10413. _fsqrts_:
  10414.     fsqrt.s        0x4(%sp),%fp0        # fsqrt w/ sgl src
  10415.     rts
  10416.  
  10417.     global        _fsqrtd_
  10418. _fsqrtd_:
  10419.     fsqrt.d        0x4(%sp),%fp0        # fsqrt w/ dbl src
  10420.     rts
  10421.  
  10422.     global        _fsqrtx_
  10423. _fsqrtx_:
  10424.     fsqrt.x        0x4(%sp),%fp0        # fsqrt w/ ext src
  10425.     rts
  10426.  
  10427.     global        _fints_
  10428. _fints_:
  10429.     fint.s        0x4(%sp),%fp0        # fint w/ sgl src
  10430.     rts
  10431.  
  10432.     global        _fintd_
  10433. _fintd_:
  10434.     fint.d        0x4(%sp),%fp0        # fint w/ dbl src
  10435.     rts
  10436.  
  10437.     global        _fintx_
  10438. _fintx_:
  10439.     fint.x        0x4(%sp),%fp0        # fint w/ ext src
  10440.     rts
  10441.  
  10442.     global        _fintrzs_
  10443. _fintrzs_:
  10444.     fintrz.s    0x4(%sp),%fp0        # fintrz w/ sgl src
  10445.     rts
  10446.  
  10447.     global        _fintrzd_
  10448. _fintrzd_:
  10449.     fintrz.d    0x4(%sp),%fp0        # fintrx w/ dbl src
  10450.     rts
  10451.  
  10452.     global        _fintrzx_
  10453. _fintrzx_:
  10454.     fintrz.x    0x4(%sp),%fp0        # fintrz w/ ext src
  10455.     rts
  10456.  
  10457. ########################################################################
  10458.  
  10459. #########################################################################
  10460. # src_zero(): Return signed zero according to sign of src operand.    #
  10461. #########################################################################
  10462.     global        src_zero
  10463. src_zero:
  10464.     tst.b        SRC_EX(%a0)        # get sign of src operand
  10465.     bmi.b        ld_mzero        # if neg, load neg zero
  10466.  
  10467. #
  10468. # ld_pzero(): return a positive zero.
  10469. #
  10470.     global        ld_pzero
  10471. ld_pzero:
  10472.     fmov.s        &0x00000000,%fp0    # load +0
  10473.     mov.b        &z_bmask,FPSR_CC(%a6)    # set 'Z' ccode bit
  10474.     rts
  10475.  
  10476. # ld_mzero(): return a negative zero.
  10477.     global        ld_mzero
  10478. ld_mzero:
  10479.     fmov.s        &0x80000000,%fp0    # load -0
  10480.     mov.b        &neg_bmask+z_bmask,FPSR_CC(%a6) # set 'N','Z' ccode bits
  10481.     rts
  10482.  
  10483. #########################################################################
  10484. # dst_zero(): Return signed zero according to sign of dst operand.    #
  10485. #########################################################################
  10486.     global        dst_zero
  10487. dst_zero:
  10488.     tst.b        DST_EX(%a1)         # get sign of dst operand
  10489.     bmi.b        ld_mzero        # if neg, load neg zero
  10490.     bra.b        ld_pzero        # load positive zero
  10491.  
  10492. #########################################################################
  10493. # src_inf(): Return signed inf according to sign of src operand.    #
  10494. #########################################################################
  10495.     global        src_inf
  10496. src_inf:
  10497.     tst.b        SRC_EX(%a0)         # get sign of src operand
  10498.     bmi.b        ld_minf            # if negative branch
  10499.  
  10500. #
  10501. # ld_pinf(): return a positive infinity.
  10502. #
  10503.     global        ld_pinf
  10504. ld_pinf:
  10505.     fmov.s        &0x7f800000,%fp0    # load +INF
  10506.     mov.b        &inf_bmask,FPSR_CC(%a6)    # set 'INF' ccode bit
  10507.     rts
  10508.  
  10509. #
  10510. # ld_minf():return a negative infinity.
  10511. #
  10512.     global        ld_minf
  10513. ld_minf:
  10514.     fmov.s        &0xff800000,%fp0    # load -INF
  10515.     mov.b        &neg_bmask+inf_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
  10516.     rts
  10517.  
  10518. #########################################################################
  10519. # dst_inf(): Return signed inf according to sign of dst operand.    #
  10520. #########################################################################
  10521.     global        dst_inf
  10522. dst_inf:
  10523.     tst.b        DST_EX(%a1)         # get sign of dst operand
  10524.     bmi.b        ld_minf            # if negative branch
  10525.     bra.b        ld_pinf
  10526.  
  10527.     global        szr_inf
  10528. #################################################################
  10529. # szr_inf(): Return +ZERO for a negative src operand or        #
  10530. #                +INF for a positive src operand.        #
  10531. #         Routine used for fetox, ftwotox, and ftentox.    #
  10532. #################################################################
  10533. szr_inf:
  10534.     tst.b        SRC_EX(%a0)        # check sign of source
  10535.     bmi.b        ld_pzero
  10536.     bra.b        ld_pinf
  10537.  
  10538. #########################################################################
  10539. # sopr_inf(): Return +INF for a positive src operand or            #
  10540. #          jump to operand error routine for a negative src operand.    #
  10541. #          Routine used for flogn, flognp1, flog10, and flog2.    #
  10542. #########################################################################
  10543.     global        sopr_inf
  10544. sopr_inf:
  10545.     tst.b        SRC_EX(%a0)        # check sign of source
  10546.     bmi.w        t_operr
  10547.     bra.b        ld_pinf
  10548.  
  10549. #################################################################
  10550. # setoxm1i(): Return minus one for a negative src operand or    #
  10551. #          positive infinity for a positive src operand.    #
  10552. #          Routine used for fetoxm1.                #
  10553. #################################################################
  10554.     global        setoxm1i
  10555. setoxm1i:
  10556.     tst.b        SRC_EX(%a0)        # check sign of source
  10557.     bmi.b        ld_mone
  10558.     bra.b        ld_pinf
  10559.  
  10560. #########################################################################
  10561. # src_one(): Return signed one according to sign of src operand.    #
  10562. #########################################################################
  10563.     global        src_one
  10564. src_one:
  10565.     tst.b        SRC_EX(%a0)         # check sign of source
  10566.     bmi.b        ld_mone
  10567.  
  10568. #
  10569. # ld_pone(): return positive one.
  10570. #
  10571.     global        ld_pone
  10572. ld_pone:
  10573.     fmov.s        &0x3f800000,%fp0    # load +1
  10574.     clr.b        FPSR_CC(%a6)
  10575.     rts
  10576.  
  10577. #
  10578. # ld_mone(): return negative one.
  10579. #
  10580.     global        ld_mone
  10581. ld_mone:
  10582.     fmov.s        &0xbf800000,%fp0    # load -1
  10583.     mov.b        &neg_bmask,FPSR_CC(%a6)    # set 'N' ccode bit
  10584.     rts
  10585.  
  10586. ppiby2:    long        0x3fff0000, 0xc90fdaa2, 0x2168c235
  10587. mpiby2:    long        0xbfff0000, 0xc90fdaa2, 0x2168c235
  10588.  
  10589. #################################################################
  10590. # spi_2(): Return signed PI/2 according to sign of src operand.    #
  10591. #################################################################
  10592.     global        spi_2
  10593. spi_2:
  10594.     tst.b        SRC_EX(%a0)         # check sign of source
  10595.     bmi.b        ld_mpi2
  10596.  
  10597. #
  10598. # ld_ppi2(): return positive PI/2.
  10599. #
  10600.     global        ld_ppi2
  10601. ld_ppi2:
  10602.     fmov.l        %d0,%fpcr
  10603.     fmov.x        ppiby2(%pc),%fp0    # load +pi/2
  10604.     bra.w        t_pinx2            # set INEX2
  10605.  
  10606. #
  10607. # ld_mpi2(): return negative PI/2.
  10608. #
  10609.     global        ld_mpi2
  10610. ld_mpi2:
  10611.     fmov.l        %d0,%fpcr
  10612.     fmov.x        mpiby2(%pc),%fp0    # load -pi/2
  10613.     bra.w        t_minx2            # set INEX2
  10614.  
  10615. ####################################################
  10616. # The following routines give support for fsincos. #
  10617. ####################################################
  10618.  
  10619. #
  10620. # ssincosz(): When the src operand is ZERO, store a one in the
  10621. #           cosine register and return a ZERO in fp0 w/ the same sign
  10622. #          as the src operand.
  10623. #
  10624.     global        ssincosz
  10625. ssincosz:
  10626.     fmov.s        &0x3f800000,%fp1
  10627.     tst.b        SRC_EX(%a0)        # test sign
  10628.     bpl.b        sincoszp
  10629.     fmov.s        &0x80000000,%fp0    # return sin result in fp0
  10630.     mov.b        &z_bmask+neg_bmask,FPSR_CC(%a6)
  10631.     rts
  10632. sincoszp:
  10633.     fmov.s        &0x00000000,%fp0    # return sin result in fp0
  10634.     mov.b        &z_bmask,FPSR_CC(%a6)
  10635.     rts
  10636.  
  10637. #
  10638. # ssincosi(): When the src operand is INF, store a QNAN in the cosine
  10639. #          register and jump to the operand error routine for negative
  10640. #          src operands.
  10641. #
  10642.     global        ssincosi
  10643. ssincosi:
  10644.     fmov.x        qnan(%pc),%fp1        # load NAN
  10645.     bra.w        t_operr
  10646.  
  10647. #
  10648. # ssincosqnan(): When the src operand is a QNAN, store the QNAN in the cosine
  10649. #          register and branch to the src QNAN routine.
  10650. #
  10651.     global        ssincosqnan
  10652. ssincosqnan:
  10653.     fmov.x        LOCAL_EX(%a0),%fp1
  10654.     bra.w        src_qnan
  10655.  
  10656. ########################################################################
  10657.  
  10658.     global        smod_sdnrm
  10659.     global        smod_snorm
  10660. smod_sdnrm:
  10661. smod_snorm:
  10662.     mov.b        DTAG(%a6),%d1
  10663.     beq.l        smod
  10664.     cmpi.b        %d1,&ZERO
  10665.     beq.w        smod_zro
  10666.     cmpi.b        %d1,&INF
  10667.     beq.l        t_operr
  10668.     cmpi.b        %d1,&DENORM
  10669.     beq.l        smod
  10670.     bra.l        dst_qnan
  10671.  
  10672.     global        smod_szero
  10673. smod_szero:
  10674.     mov.b        DTAG(%a6),%d1
  10675.     beq.l        t_operr
  10676.     cmpi.b        %d1,&ZERO
  10677.     beq.l        t_operr
  10678.     cmpi.b        %d1,&INF
  10679.     beq.l        t_operr
  10680.     cmpi.b        %d1,&DENORM
  10681.     beq.l        t_operr
  10682.     bra.l        dst_qnan
  10683.  
  10684.     global        smod_sinf
  10685. smod_sinf:
  10686.     mov.b        DTAG(%a6),%d1
  10687.     beq.l        smod_fpn
  10688.     cmpi.b        %d1,&ZERO
  10689.     beq.l        smod_zro
  10690.     cmpi.b        %d1,&INF
  10691.     beq.l        t_operr
  10692.     cmpi.b        %d1,&DENORM
  10693.     beq.l        smod_fpn
  10694.     bra.l        dst_qnan
  10695.  
  10696. smod_zro:
  10697. srem_zro:
  10698.     mov.b        SRC_EX(%a0),%d1        # get src sign
  10699.     mov.b        DST_EX(%a1),%d0        # get dst sign
  10700.     eor.b        %d0,%d1            # get qbyte sign
  10701.     andi.b        &0x80,%d1
  10702.     mov.b        %d1,FPSR_QBYTE(%a6)
  10703.     tst.b        %d0
  10704.     bpl.w        ld_pzero
  10705.     bra.w        ld_mzero
  10706.  
  10707. smod_fpn:
  10708. srem_fpn:
  10709.     clr.b        FPSR_QBYTE(%a6)
  10710.     mov.l        %d0,-(%sp)
  10711.     mov.b        SRC_EX(%a0),%d1        # get src sign
  10712.     mov.b        DST_EX(%a1),%d0        # get dst sign
  10713.     eor.b        %d0,%d1            # get qbyte sign
  10714.     andi.b        &0x80,%d1
  10715.     mov.b        %d1,FPSR_QBYTE(%a6)
  10716.     cmpi.b        DTAG(%a6),&DENORM
  10717.     bne.b        smod_nrm
  10718.     lea        DST(%a1),%a0
  10719.     mov.l        (%sp)+,%d0
  10720.     bra        t_resdnrm
  10721. smod_nrm:
  10722.     fmov.l        (%sp)+,%fpcr
  10723.     fmov.x        DST(%a1),%fp0
  10724.     tst.b        DST_EX(%a1)
  10725.     bmi.b        smod_nrm_neg
  10726.     rts
  10727.  
  10728. smod_nrm_neg:
  10729.     mov.b        &neg_bmask,FPSR_CC(%a6)    # set 'N' code
  10730.     rts
  10731.  
  10732. #########################################################################
  10733.     global        srem_snorm
  10734.     global        srem_sdnrm
  10735. srem_sdnrm:
  10736. srem_snorm:
  10737.     mov.b        DTAG(%a6),%d1
  10738.     beq.l        srem
  10739.     cmpi.b        %d1,&ZERO
  10740.     beq.w        srem_zro
  10741.     cmpi.b        %d1,&INF
  10742.     beq.l        t_operr
  10743.     cmpi.b        %d1,&DENORM
  10744.     beq.l        srem
  10745.     bra.l        dst_qnan
  10746.  
  10747.     global        srem_szero
  10748. srem_szero:
  10749.     mov.b        DTAG(%a6),%d1
  10750.     beq.l        t_operr
  10751.     cmpi.b        %d1,&ZERO
  10752.     beq.l        t_operr
  10753.     cmpi.b        %d1,&INF
  10754.     beq.l        t_operr
  10755.     cmpi.b        %d1,&DENORM
  10756.     beq.l        t_operr
  10757.     bra.l        dst_qnan
  10758.  
  10759.     global        srem_sinf
  10760. srem_sinf:
  10761.     mov.b        DTAG(%a6),%d1
  10762.     beq.w        srem_fpn
  10763.     cmpi.b        %d1,&ZERO
  10764.     beq.w        srem_zro
  10765.     cmpi.b        %d1,&INF
  10766.     beq.l        t_operr
  10767.     cmpi.b        %d1,&DENORM
  10768.     beq.l        srem_fpn
  10769.     bra.l        dst_qnan
  10770.  
  10771. #########################################################################
  10772.  
  10773.     global        sscale_snorm
  10774.     global        sscale_sdnrm
  10775. sscale_snorm:
  10776. sscale_sdnrm:
  10777.     mov.b        DTAG(%a6),%d1
  10778.     beq.l        sscale
  10779.     cmpi.b        %d1,&ZERO
  10780.     beq.l        dst_zero
  10781.     cmpi.b        %d1,&INF
  10782.     beq.l        dst_inf
  10783.     cmpi.b        %d1,&DENORM
  10784.     beq.l        sscale
  10785.     bra.l        dst_qnan
  10786.  
  10787.     global        sscale_szero
  10788. sscale_szero:
  10789.     mov.b        DTAG(%a6),%d1
  10790.     beq.l        sscale
  10791.     cmpi.b        %d1,&ZERO
  10792.     beq.l        dst_zero
  10793.     cmpi.b        %d1,&INF
  10794.     beq.l        dst_inf
  10795.     cmpi.b        %d1,&DENORM
  10796.     beq.l        sscale
  10797.     bra.l        dst_qnan
  10798.  
  10799.     global        sscale_sinf
  10800. sscale_sinf:
  10801.     mov.b        DTAG(%a6),%d1
  10802.     beq.l        t_operr
  10803.     cmpi.b        %d1,&QNAN
  10804.     beq.l        dst_qnan
  10805.     bra.l        t_operr
  10806.  
  10807. ########################################################################
  10808.  
  10809.     global        sop_sqnan
  10810. sop_sqnan:
  10811.     mov.b        DTAG(%a6),%d1
  10812.     cmpi.b        %d1,&QNAN
  10813.     beq.l        dst_qnan
  10814.     bra.l        src_qnan
  10815.  
  10816. #########################################################################
  10817. # norm(): normalize the mantissa of an extended precision input. the    #
  10818. #      input operand should not be normalized already.        #
  10819. #                                    #
  10820. # XDEF ****************************************************************    #
  10821. #    norm()                                #
  10822. #                                    #
  10823. # XREF **************************************************************** #
  10824. #    none                                #
  10825. #                                    #
  10826. # INPUT *************************************************************** #
  10827. #    a0 = pointer fp extended precision operand to normalize        #
  10828. #                                    #
  10829. # OUTPUT ************************************************************** #
  10830. #     d0 = number of bit positions the mantissa was shifted        #
  10831. #    a0 = the input operand's mantissa is normalized; the exponent    #
  10832. #         is unchanged.                        #
  10833. #                                    #
  10834. #########################################################################
  10835.     global        norm
  10836. norm:
  10837.     mov.l        %d2, -(%sp)        # create some temp regs
  10838.     mov.l        %d3, -(%sp)
  10839.  
  10840.     mov.l        FTEMP_HI(%a0), %d0    # load hi(mantissa)
  10841.     mov.l        FTEMP_LO(%a0), %d1    # load lo(mantissa)
  10842.  
  10843.     bfffo        %d0{&0:&32}, %d2    # how many places to shift?
  10844.     beq.b        norm_lo            # hi(man) is all zeroes!
  10845.  
  10846. norm_hi:
  10847.     lsl.l        %d2, %d0        # left shift hi(man)
  10848.     bfextu        %d1{&0:%d2}, %d3    # extract lo bits
  10849.  
  10850.     or.l        %d3, %d0        # create hi(man)
  10851.     lsl.l        %d2, %d1        # create lo(man)
  10852.  
  10853.     mov.l        %d0, FTEMP_HI(%a0)    # store new hi(man)
  10854.     mov.l        %d1, FTEMP_LO(%a0)    # store new lo(man)
  10855.  
  10856.     mov.l        %d2, %d0        # return shift amount
  10857.     
  10858.     mov.l        (%sp)+, %d3        # restore temp regs
  10859.     mov.l        (%sp)+, %d2
  10860.  
  10861.     rts
  10862.  
  10863. norm_lo:
  10864.     bfffo        %d1{&0:&32}, %d2    # how many places to shift?
  10865.     lsl.l        %d2, %d1        # shift lo(man)
  10866.     add.l        &32, %d2        # add 32 to shft amount
  10867.  
  10868.     mov.l        %d1, FTEMP_HI(%a0)    # store hi(man)
  10869.     clr.l        FTEMP_LO(%a0)        # lo(man) is now zero
  10870.  
  10871.     mov.l        %d2, %d0        # return shift amount
  10872.     
  10873.     mov.l        (%sp)+, %d3        # restore temp regs
  10874.     mov.l        (%sp)+, %d2
  10875.  
  10876.     rts
  10877.  
  10878. #########################################################################
  10879. # unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO    #
  10880. #        - returns corresponding optype tag            #
  10881. #                                    #
  10882. # XDEF ****************************************************************    #
  10883. #    unnorm_fix()                            #
  10884. #                                    #
  10885. # XREF **************************************************************** #
  10886. #    norm() - normalize the mantissa                    #
  10887. #                                    #
  10888. # INPUT *************************************************************** #
  10889. #    a0 = pointer to unnormalized extended precision number        #
  10890. #                                    #
  10891. # OUTPUT ************************************************************** #
  10892. #    d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO    #
  10893. #    a0 = input operand has been converted to a norm, denorm, or    #
  10894. #         zero; both the exponent and mantissa are changed.        #
  10895. #                                    #
  10896. #########################################################################
  10897.  
  10898.     global        unnorm_fix
  10899. unnorm_fix:
  10900.     bfffo        FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
  10901.     bne.b        unnorm_shift        # hi(man) is not all zeroes
  10902.  
  10903. #
  10904. # hi(man) is all zeroes so see if any bits in lo(man) are set
  10905. #
  10906. unnorm_chk_lo:
  10907.     bfffo        FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
  10908.     beq.w        unnorm_zero        # yes
  10909.  
  10910.     add.w        &32, %d0        # no; fix shift distance
  10911.  
  10912. #
  10913. # d0 = # shifts needed for complete normalization
  10914. #
  10915. unnorm_shift:
  10916.     clr.l        %d1            # clear top word
  10917.     mov.w        FTEMP_EX(%a0), %d1    # extract exponent
  10918.     and.w        &0x7fff, %d1        # strip off sgn
  10919.  
  10920.     cmp.w        %d0, %d1        # will denorm push exp < 0?
  10921.     bgt.b        unnorm_nrm_zero        # yes; denorm only until exp = 0
  10922.  
  10923. #
  10924. # exponent would not go < 0. therefore, number stays normalized
  10925. #
  10926.     sub.w        %d0, %d1        # shift exponent value
  10927.     mov.w        FTEMP_EX(%a0), %d0    # load old exponent
  10928.     and.w        &0x8000, %d0        # save old sign
  10929.     or.w        %d0, %d1        # {sgn,new exp}
  10930.     mov.w        %d1, FTEMP_EX(%a0)    # insert new exponent
  10931.  
  10932.     bsr.l        norm            # normalize UNNORM
  10933.  
  10934.     mov.b        &NORM, %d0        # return new optype tag
  10935.     rts
  10936.  
  10937. #
  10938. # exponent would go < 0, so only denormalize until exp = 0
  10939. #
  10940. unnorm_nrm_zero:
  10941.     cmp.b        %d1, &32        # is exp <= 32?
  10942.     bgt.b        unnorm_nrm_zero_lrg    # no; go handle large exponent
  10943.  
  10944.     bfextu        FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
  10945.     mov.l        %d0, FTEMP_HI(%a0)    # save new hi(man)
  10946.  
  10947.     mov.l        FTEMP_LO(%a0), %d0    # fetch old lo(man)
  10948.     lsl.l        %d1, %d0        # extract new lo(man)
  10949.     mov.l        %d0, FTEMP_LO(%a0)    # save new lo(man)
  10950.  
  10951.     and.w        &0x8000, FTEMP_EX(%a0)    # set exp = 0
  10952.  
  10953.     mov.b        &DENORM, %d0        # return new optype tag
  10954.     rts
  10955.  
  10956. #
  10957. # only mantissa bits set are in lo(man)
  10958. #
  10959. unnorm_nrm_zero_lrg:
  10960.     sub.w        &32, %d1        # adjust shft amt by 32
  10961.  
  10962.     mov.l        FTEMP_LO(%a0), %d0    # fetch old lo(man)
  10963.     lsl.l        %d1, %d0        # left shift lo(man)
  10964.  
  10965.     mov.l        %d0, FTEMP_HI(%a0)    # store new hi(man)
  10966.     clr.l        FTEMP_LO(%a0)        # lo(man) = 0
  10967.  
  10968.     and.w        &0x8000, FTEMP_EX(%a0)    # set exp = 0
  10969.  
  10970.     mov.b        &DENORM, %d0        # return new optype tag
  10971.     rts
  10972.  
  10973. #
  10974. # whole mantissa is zero so this UNNORM is actually a zero
  10975. #
  10976. unnorm_zero:
  10977.     and.w        &0x8000, FTEMP_EX(%a0)     # force exponent to zero
  10978.  
  10979.     mov.b        &ZERO, %d0        # fix optype tag
  10980.     rts
  10981.